字符指针 : Creating dynamic string array, 赋值并传递给其他函数和其他小家伙 - C

标签 c string pointers malloc

关闭。这个问题需要更多focused .它目前不接受答案。












想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post .

3年前关闭。




Improve this question




我正在研究与动态内存一起使用的指针,我已经完成了一个 MCVE 代码,我在其中创建了一个动态字符串数组(指向 char 的指针的指针),用 malloc 初始化它,分配值,将它发送到一个打印它们的函数并返回确定,然后释放内存(完整代码在帖子的底部。我建议在问题之前查看完整代码)。

这样做,我有疑问:

  • 字符串数组应该像这样创建:
    char **stringArray = NULL;
    stringArray = malloc(NUM_OF_ELEMENTS*sizeof(char)); 
    for (i = 0; i < NUM_OF_ELEMENTS; i++)
        stringArray[i] = malloc((STRING_LENGTH+1)*sizeof(char));
    /*
        FIRST: Init a double pointer to char
        SECOND: Create number of elements of the array (number of strings)
                When is created the number of elements... is not needed end it with '\0' char, right?
                When malloc is done... is needed mult it *sizeof(char)? In case it is not like that, is needed mult it *sizeof(anything)?
        THIRD: Create length of each string
    */
    
  • 输入(由用户,或手动)是否正确完成?
    // Creating elements
    // User input
    for (i = 0; i < NUM_OF_ELEMENTS-1; i++) {
        printf("Input: %i with letters (One, Two,..): ", i+1);
        gets(userInput);
        strcpy(stringArray[i], userInput); // stringArray[0] = "One"; stringArray[1] = "Two"
    }
    // Manually
    strcpy(stringArray[NUM_OF_ELEMENTS-1], "Three"); // stringArray[2] = "Three"
    
  • 返回字符串的函数也应该是指向 char 的指针,对吗?
    char *functionWhichReturnsOneString() {
        return "string";
    }
    
  • 是否按值和引用正确传递/接收参数?
    printElementsOfStringArrayPassedByValue(stringArray) // Call to function
    char *printElementsOfStringArrayPassedByValue(char **stringArray) {
        int i = 0;
    
        for (i = 0; i < NUM_OF_ELEMENTS; i++)
            printf("%s\n", stringArray[i]);
    
        return "OK";
    }
    
    printElementsOfStringArray2PassedByReference(&stringArray) // Call to function
    char *printElementsOfStringArray2PassedByReference(char ***stringArray) {
        int i = 0;
    
        for (i = 0; i < NUM_OF_ELEMENTS; i++)
            printf("%s\n", (*stringArray)[i]); // Is it equal to: *((*stringArray)+i) ?
    
        return "OK";
    }
    
  • 等于:(*stringArray)[i])和:*((*stringArray)+i) , 对?



  • 完整代码为:
    #include <stdio.h>
    #include <string.h>
    
    #define NUM_OF_ELEMENTS 3
    #define STRING_LENGTH 35
    
    char *printElementsOfStringArrayPassedByValue(char **stringArray) {
        int i = 0;
    
        for (i = 0; i < NUM_OF_ELEMENTS; i++)
            printf("%s\n", stringArray[i]);
    
        return "OK";
    }
    
    char *printElementsOfStringArray2PassedByReference(char ***stringArray) {
        int i = 0;
    
        for (i = 0; i < NUM_OF_ELEMENTS; i++)
            printf("%s\n", (*stringArray)[i]); // Is it equal to: *((*stringArray)+i) ?
    
        return "OK";
    }
    
    int main(void) {
        // Variables
        int i = 0;
        char userInput[STRING_LENGTH] = {'\0'};
        char **stringArray = NULL;
        char returnedValue[STRING_LENGTH] = {'\0'};
    
        // Creating array of strings
        stringArray = malloc(NUM_OF_ELEMENTS*sizeof(char)); // Here is correct: *sizeof(char)?; Is not needed \0 char?
    
        // Creating each element of the array
        for (i = 0; i < NUM_OF_ELEMENTS; i++)
            stringArray[i] = malloc((STRING_LENGTH+1)*sizeof(char));
    
        // Creating elements
            // User input
            for (i = 0; i < NUM_OF_ELEMENTS-1; i++) {
                printf("Input: %i with letters (One, Two,..): ", i+1);
                gets(userInput);
                strcpy(stringArray[i], userInput); // stringArray[0] = "One"; stringArray[1] = "Two"
            }
            // Manually
            strcpy(stringArray[NUM_OF_ELEMENTS-1], "Three"); // stringArray[2] = "Three"
    
        strcpy(returnedValue, printElementsOfStringArrayPassedByValue(stringArray)); // Pass by value and return a string
        printf("%s - Ended print 1\n", returnedValue);
        strcpy(returnedValue, printElementsOfStringArray2PassedByReference(&stringArray)); // Pass by reference and return a string
        printf("%s - Ended print 2\n", returnedValue);
    
        // Freeing memory
        for (i = 0; i < NUM_OF_ELEMENTS; i++) {
            free(stringArray[i]);
            stringArray[i] = NULL;
        }
        free(stringArray);
        stringArray = NULL;
    
        return 0;
    }
    

    谢谢你的帮助。

    最佳答案

    - 该方法没问题,但第一个 sizeof 参数是错误的(stringArray 的类型为 char**,而不是 char*),最好将 sizeof 与 malloc 一起使用,如下所示:

     char **stringArray = NULL;
     stringArray = malloc(NUM_OF_ELEMENTS * sizeof(*stringArray)); 
     for (i = 0; i < NUM_OF_ELEMENTS; i++)
         stringArray[i] = malloc((STRING_LENGTH+1) * sizeof(*stringArray[i]));
    

    而对于编程高手,最好使用 calloc 来处理整数溢出:
     char **stringArray = NULL;
     stringArray = calloc(NUM_OF_ELEMENTS, sizeof(*stringArray)); 
     assert(stringArray != NULL);
     for (i = 0; i < NUM_OF_ELEMENTS; i++) {
         stringArray[i] = calloc(STRING_LENGTH+1, sizeof(*stringArray[i]));
         assert(stringArray[i] != NULL); 
     }
    

    - 是的,不要使用 gets .删除 gets从内存里。使用 fgets(userInput, sizeof(userInput), stdin);- 您必须确保字符串的存储持续时间比函数长。在您的示例中,您返回一个指向 string literal 的指针。 .并且字符串文字具有静态存储持续时间,就像您在文件范围内声明它一样,所以在这里很好。如果你要返回一个指向 compound literals 的指针或者你会在堆栈上初始化字符串,这将是一个问题。这样的函数将返回一个指向字符串的指针,但是一旦函数退出,您不知道该字符串是否存在,因为该字符串在函数返回后不再存在。
    你也可以:
    static char *string_to_return = "string";
    char *functionWhichReturnsOneString_global() {
        return string_to_return;
    }
    char *functionWhichReturnsOneString_static() {
        static char *string_to_return_2 = "string";
        return string_to_return;
    }
    

    这样 string_to_return 具有静态存储持续时间,它将在全局范围内可用。另一种方法是使用 malloc(或 strdup)为字符串分配内存并返回指向该内存的指针(记住之后释放它(!)):
    char *functionWhichReturnsOneString_malloc() {
        char *string_to_return = malloc(sizeof("string"));
        memcpy(string_to_return, "string", sizeof("string"));
        return string_to_return;
    }
    char *functionWhichReturnsOneString_strdup() {
        return strdup("string");
    }
    

    - 功能完全相同。 stringArray 是指向字符数组的指针数组。它是一个指针,指向一个指针数组,每个指针指向一个字符数组。将 stringArray 传递给函数足以修改存储在数组中的字符(作为 stringArray 指向这些数组),例如。调整这些数组的大小。如果您传递 &stringArray,您的函数可能会更改数组的数量(即 NUM_OF_ELEMENTS)(不是特定数组中的字符数,而是数组本身的数量)。你可以做 *stringArray = realloc(*stringArray, (NUM_OF_ELEMENTS+20)*sizeof(**stringArray));- 是的。表达式 A[B]等于 B[A]等于 *(B+A) .搞笑,这也等于:*i[*stringArray] ,但这种形式伤害了我的眼睛。

    关于字符指针 : Creating dynamic string array, 赋值并传递给其他函数和其他小家伙 - C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49721815/

    相关文章:

    c - 如何将4个字符组合成1个字符

    C++ 如何将指针 vector (双指针)作为常量传递给函数

    c - C程序中的多线程

    c - 如何避免 realloc 溢出?

    php - 将 float 格式化为两位小数

    java - 字符串列表的比较器

    c++ - 如何将常量指针传递给类中的方法

    c - 每次返回指针时都必须使用 malloc

    c - 使用 sscanf 将带有括号和逗号的字符串拆分为更小的变量

    Java 更短的加密