简体   繁体   English

C 中的字符数组最大大小如何确定?

[英]How is a char array maximum size in C determined?

Learning C and checking the reference from the GNU reference manual .学习 C 并查看GNU 参考手册中的参考。 I don't understand how is the maximum size that can be allocated to a char array defined in an exact way.我不明白可以分配给以精确方式定义的 char 数组的最大大小。 In my test program when the allocated size for a string array is "small" it works fine but when it is "large" the program start behaving erratically.在我的测试程序中,当字符串数组的分配大小为“小”时,它工作正常,但当它为“大”时,程序开始表现不规律。 The compiler throws no errors when it gets compiled but during runtime, it is affecting the correctness of my program that uses strtok() , missing some valid tokens in the result.编译器在编译时不会抛出错误,但在运行时,它会影响我使用strtok()的程序的正确性,结果中缺少一些有效的标记。

Taking as input (considering 5 an arbitrary "small" array size):作为输入(考虑 5 任意“小”数组大小):

>> 5 
>> 19 65 41 65 56

The sum output is 246 so it works well总和 output 是 246 所以它运作良好

But taking as input (considering 53 an arbitrary "large" array size):但作为输入(考虑 53 任意“大”数组大小):

>> 53
>> 19 65 41 65 56 74 76 71 29 44 45 9 66 37 59 6 71 8 30 29 41 31 96 86 11 14 29 24 17 65 88 23 21 49 31 96 72 39 83 96 96 63 44 72 85 38 5 11 70 36 90 49 76

The sum output is 2247 which is wrong (correct is 2647). output 的总和是 2247,这是错误的(正确的是 2647)。 This incorrectness holds for any "large" number of array_size这种不正确性适用于任何“大量” array_size

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(){
  /*Array size is the amount of integers that will be introduced later. E.g: 5 (introducting 5 integers next) -> 3 4 5 6 7*/
  /*The numbers are 1 <= n <= 1000 */
  int array_size;  
  scanf("%d", &array_size);
  printf("The array size you introduced is %d\n", array_size);  

  /* Given that the integers introduced can have at most 4 digits and they are separated by a whitespace character, array_size*5 is allocated */
  char sentence[array_size * 5];
  scanf("\n");
  scanf("%[^\n]%*c", sentence);

  char delimiter = ' ';
  char *token;
  token = strtok(sentence, &delimiter);
  int sumResult; 
  printf("The token %d is %s\n", 1, token);   
                     
  while (token != NULL) {                
    sumResult = sumResult + atoi(token);
    token = strtok(NULL, &delimiter);
    printf("The token is %s\n", token);
  }
  
  printf("%d\n", sumResult);
}

There are (at least) three errors in the program:程序中有(至少)三个错误:

int sumResult; leaves sumResult uninitialized.使sumResult未初始化。 It must be initialized to zero, as with int sumResult = 0;它必须初始化为零,如int sumResult = 0; . .

strtok(sentence, &delimiter) passes the address of a single character to strtok . strtok(sentence, &delimiter)将单个字符的地址传递给strtok For the second parameter, strtok expects a pointer to the first character of a string, meaning a sequence of characters terminating by a null character.对于第二个参数, strtok需要一个指向字符串第一个字符的指针,即以 null 字符结尾的字符序列。 Change the definition of delimeter to char delimiter[] = " ";将分隔符的定义改为char delimiter[] = " "; delimeter and change both strtok calls to strtok(sentence, delimiter);并将两个strtok调用更改为strtok(sentence, delimiter); . .

printf("The token is %s\n", token); is executed once when token is a null pointer.token是 null 指针时执行一次。 For %s , printf should be passed a pointer to the first character of a string, not a null pointer.对于%sprintf应该传递一个指向字符串第一个字符的指针,而不是 null 指针。 This can be remedied by moving this printf to be the first line in the while loop and deleting the prior printf("The token %d is %s\n", 1, token);这可以通过将此printf移动到while循环中的第一行并删除之前的printf("The token %d is %s\n", 1, token);解决。 . .

int sumResult; 

When sumResult is not initialized, it does not have a determined value.sumResult未初始化时,它没有确定的值。 In the language of the C standard, is value is indeterminate , meaning that the program may behave as if sumResult has no fixed value at all;在 C 标准的语言中,is value is indeterminate意味着程序可能表现得好像sumResult根本没有固定值; it may appear to have different values at different times.它可能在不同的时间看起来有不同的值。 Further, in this program, using it without it being initialized results in the entire behavior of the program not being defined by the C standard.此外,在这个程序中,在没有初始化的情况下使用它会导致程序的整个行为不是由 C 标准定义的。

int sumResult = 0; 

In the C language object (variables) have different storage durations.在 C 语言中 object(变量)有不同的存储期限。

  1. Variables defined in the function scope have automatic storage duration and are not automatically initialized. function scope 中定义的变量具有自动存储期限,不会自动初始化。
  2. Variables defined outside of any function (file scope) and variables defined in functions but declared as static have static storage duration and are automatically initialized (to zero or equivalent for their type) on program startup.在任何 function(文件范围)之外定义的变量和在函数中定义但声明为static的变量具有static存储持续时间,并且在其启动自动初始化(为零或等效类型)。

You can do it much easier:你可以更容易地做到这一点:

int main(void)
{
/*Array size is the amount of integers that will be introduced later. E.g: 5 (introducting 5 integers next) -> 3 4 5 6 7*/
/*The numbers are 1 <= n <= 1000 */
    size_t array_size;  
    if(scanf("%zu",&array_size) != 1) {/* error handling */}
    printf("The array size you introduced is %zu\n", array_size);  
    int array[array_size];

    /* Given that the integers introduced can have at most 4 digits and they are separated by a whitespace character, array_size*5 is allocated */
    int sumResult = 0; 

    for(size_t num = 0; num < array_size; num++)
    {
        if(scanf("%d", array + num) != 1 ) {/* error handling */; break;}
        sumResult += array[num];
    }
    printf("%d\n", sumResult);
}

https://godbolt.org/z/zoWz1cjc7 https://godbolt.org/z/zoWz1cjc7

Your code "repaired"您的代码“已修复”

int main(){
  /*Array size is the amount of integers that will be introduced later. E.g: 5 (introducting 5 integers next) -> 3 4 5 6 7*/
  /*The numbers are 1 <= n <= 1000 */
  int array_size;  
  scanf("%d", &array_size);
  printf("The array size you introduced is %d\n", array_size);  

  /* Given that the integers introduced can have at most 4 digits and they are separated by a whitespace character, array_size*5 is allocated */
  char sentence[array_size * 5];
  scanf("\n");
  scanf("%[^\n]%*c", sentence);

  char delimiter[] = " ";
  char *token;
  token = strtok(sentence, delimiter);
  int sumResult = 0; 
  printf("The token %d is %s\n", atoi(token), token);   
                     
  while (token != NULL) {                
    sumResult = sumResult + atoi(token);
    printf("The token is %s %d\n", token, atoi(token));
    token = strtok(NULL, delimiter);
  }
  
  printf("%d\n", sumResult);
}

https://godbolt.org/z/1qj3acn55 https://godbolt.org/z/1qj3acn55

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM