好吧所以我只是在制作随机程序并看到他们的输出来理解事情是如何工作的,我注意到有关整数/浮点数组的一个奇怪的事情。与char数组不同,'\ 0'字符不会在最后输入的元素之后直接存储到数组中。在整数数组中,它在最后一个元素之后存储两个元素,在float中存储它的四个元素。这是展示这个奇怪事实的代码。请帮助我理解为什么会这样。
#include <stdio.h>
#include <string.h>
void foo(int* x)
{
while ( *(x) != '\0' )
{
printf("%i ",*x);
++x;
}
}
void foo1(float* x)
{
while ( *(x) != '\0')
{
printf("%.1f ",*x);
++x;
}
}
void foo2(char* x)
{
while( *(x) != '\0' )
{
printf("%c",*x);
++x;
}
}
int main(void)
{
int a[4] = {1,2,3,4};
float b[4] = {1.1,2.2,3.3,4.4};
char name[] = "Muneeb";
foo(a);
printf("\n\n");
foo1(b);
printf("\n\n");
foo2(name);
return 0;
}
输出:
1 2 3 4 -12345677723 -1623562626
1.1 2.2 3.3 4.4 0.0 0.0 0.0 0.0 -0.0 -1.3
答案 0 :(得分:10)
通常,在数组结束后没有零元素。你不能假设有;这种代码可以很容易地段错误。你发现零只是巧合。
特别是在char
数组中,此规则是相同的。但是,像"Hello, world!"
这样的文字字符串实际上比通过计算字符所获得的字符串长一char
。这是equivalent to char[13]
{'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\0'}
char
。使用'\0'
s的许多库函数都期望终止*(x) != '\0'
;对于其他类型的数组通常不存在这样的期望,您需要明确地传递长度。
另请注意,您的'\0'
treats int
为float
或*x != 0
零,相当于*x != 0.0f
或{{ 1}}(对于不同函数中的不同类型的x
)。如果你已经在其中一个数组中存储了一个实际的0,它就会计算到那个。
由于int
或float
数组没有特殊的标记惯例(因为0
和0.0f
通常是放入数组中的完全合理的值),所以你应该创建一个单独的size_t
变量来跟踪数组的长度。然后,如果你需要创建一个作用于数组的函数,你也可以给它一个length
参数并让它迭代到那个。例如:
void foo(int* x, size_t length)
{
for (size_t i = 0; i < length; ++i)
{
printf("%i ", x[i]);
}
}
(我在这里使用size_t
,因为它通常表示内存中结构的大小。)
然后你可以用foo(a, 4);
来调用它。如果您需要可变大小的数组,则可以在创建size_t a_length
时创建a
变量,并在a
的大小更改时更新它。
您有时甚至可能希望使用char
数组执行此操作,例如,如果您有可能包含零字节的二进制数据,或者因为扫描字符串末尾需要时间而您通常不需要看看每个角色。
答案 1 :(得分:2)
您将字符数组与字符串混淆。在C中,字符串不是特定的数据类型;它们是使用字符数组实现的。字符串的结尾由NUL终结符指示,但字符串的结尾不一定是可能更大的数组的结尾,而字符数组根本不需要表示字符串。
您观察到其他数组类型具有零终止符(超出数组末尾或其他方式)是错误的结论 - 您在 proximity 中观察到的结尾处的零完全是巧合。