2016-08-13 203 views
-2

我有一个问题,以更好地理解数组和空字节如何工作在C中。C数组和空字节

比方说,我有一个13个单元格的int数组。 比方说,我希望细胞数量:1,2,3和10有一个值。其他剩下的默认值会自动获取nullchar \ 0作为值?

我对\ 0的理解是,nullbyte总是在数组的末尾,它的功能是告诉程序数组在哪里结束。但似乎是错误的

我写了一个简单的PROG键确认,似乎是这样的:

int nums[13] = {1,2,3}; 
nums[10] = 69; 
int i; 
for(i=0;i<13;i++) { 
    if(nums[i]=='\0') { 
     printf("null char found! in position: %d\n",i); 
    } 
    else { 
     printf("element: %d found in position: %d of int array\n",nums[i],i); 
    } 
} 

return 0; 

这里是输出:

元素:1的位点发现:INT 0阵列

元件:2的位点发现:int数组的1

元件:3在位置上发现:int数组的2

发现空字符!在位置:3

找到空字符!在位置:4

找到空字符!在位置:5

找到空字符!在位置:6

找到空字符!在位置:7

找到空字符!在位置:8

找到空字符!在位置:9

元件:69在位置上发现:int数组的10

空焦炭找到!在位置:11

找到空字符!在位置:12

| 1 | | 2 | | 3 | | \ 0 | | \ 0 | | \ 0 | | \ 0 | | \ 0 | | \ 0 | | 69 | | \ 0 | | \ 0 | | \ 0 |

那么为什么默认单元格设置为\ 0值?而不是被留下空作为例子?

空字符不应该只在整个数组的末尾一次? 谢谢

+0

对于标量,静态分配的内存填充0或对指针填充NULL(\ 0)。如果你把\ 0作为标量,它将被转换为0.没有“空”之类的东西。您不应该将NULL(\ 0)与int进行比较,而是使用文字0. – Tibrogargan

+4

“我对\ 0的理解是,nullbyte总是在数组的末尾..”是完全错误的。您正在混淆常规数组和C字符串。 – usr2564301

+0

@Tibrogargan'\ 0'(NUL字符)与'NULL'指针不同。 '\ 0'是一个所有位都设置为0的字节,它总是与“int”0相等。 – Kninnug

回答

3

在C中没有要求阵列最后需要\0。 NUL-终止子仅仅用于字符串(其通常具有charwchar_t或其他字符类型)的C 字符串。在C字符串中,\0字节也不必位于包含它的数组的末尾,但它必须位于字符串部分的末尾。在阵列中的任何位置都有0是完全有效的。但是,如果该数组用作字符串,那么标准C字符串函数将解释具有最低索引的0来表示字符串的结尾。

当在

int nums[13] = {1,2,3}; 

声明在C变量(nums)配有一个初始化({1,2,3})未在初始化(3至12)中提到的所有索引具有其值初始化为0。数组中没有“空”单元是不可能的。所有的单元格都会有一个值,这取决于程序(mer)什么值可以被视为空的。

1

C类型对应于内存,而内存没有真正的“空”概念。有些语言可以通过放置一些“空”常量(例如Python有None)来使所有(或几乎)都变为“空”,但C不允许这样做。不允许的原因之一是它迫使你对空的状态有一个特殊的通用模式,并且这具有低层次的影响。例如,一个字符可以包含从0到255的任何值。这是因为字符占用8位。如果您还希望在不牺牲可能的字符值的情况下拥有一个空状态,那么您至少需要再多一位,因为可以出于合法原因使用其他8位,并且由于很多原因,这是不受欢迎的。

对于您的数组,您正在使用的初始化语法将每个未指定的元素设置为零。如果你写:

char foo[4] = {1, 2, 3, 4}; 

然后每一个元素都有一个值(注意它到底没有空字节,因为数组并不需要必须在一个空字节结束,但是,如果你是使用它们作为字符串,那么他们非常应该)。如果你写:

char foo[4] = {1, 2}; 

元素0和1有一个规定值,但2和3不这样做,并与下面的语法C会认为你想给他们为零。在另一方面,如果你写:

char foo[4]; 

你没有给予任何价值的任何元素,在这种情况C不会在所有的数组初始化。从它读取它将是未定义的行为;在实践中,通常情况下,元素将采用之前存储在其存储位置的任何值。

-1

首先,你正在将C字符串与常规数组混淆。对于字符串,char数组末尾总是有一个\0。它表示字符串的结尾。例如,假设你有这样的:

char myText[] = "hello"; 

在这种情况下,数组的地方是这样的:

 

    myText[0] = 'h'; 
    myText[1] = 'e'; 
    myText[2] = 'l'; 
    myText[3] = 'l'; 
    myText[4] = 'o'; 
    myText[5] = '\0'; 

但是,数组不'\0'终止。再举一个例子:

int myArray[3] = {1, 2, 3}; 

根据您的规则,因为数组有一个'\0'终止,这不是一个法律声明,因为我们只给出数组3个元素,而不是4,我们将需要4种元素包括一个'\0'。然而,这在C中是一个完全合法的陈述。很明显,在数组中不需要用于的空间,只是在C字符串的末尾。

还要注意的是'\0'相当于整数,如Kninnug在评论中指出:

\0(空字符)不一样的NULL指针。 \0是设置为0的所有位,这将总是等于为int 0

所以一个字节,在你的程序,你可以只同样检查:

if(nums[i] == 0) 

现在,让我们证明你为什么得到你的输出。

空字符不应该只在整个数组的末尾一次?

否。剩下的任何其他元素将被初始化为零值。所以这就是为什么你看到你有输出;不是num[0],num[1],num[2]num[10]的元素将被初始化为零。既然你检查\0(也0),那么其他一切与没有这些元素将是0


由于alk在评论中指出,空字符和空指针文字是不同的。在C字符串的末尾,您会看到空字符(NUL),即'/0'或0.但是,空指针字面量(NULL)不同。

+0

任何人都可以解释倒票,所以我可以改善这个职位吗? – iRove

+0

NUL(空字符的名称)和NULL(空指针字面)是不同种类的动物。 – alk

+0

C- C-“string”是一个字符数组,其中至少有一个元素等于NUL,空字符(等于''\ 0''等于'0')。字符数组不一定是C-字符串。 – alk

0

NULL定义为(无效*)0 - 它是零与通用PTR铸造, 至极等于NULL字符的(\ 0)的ASCII码 - 0

阵列不需要结束与任何特殊字符/数字。

串就需要使用特殊的字符来结束,原因很简单,它可以让功能至极运行在字符串“知道”里的字符串结尾,例如:

char str[100] = {'h','e','l','l','o',0}; // same as {'h','e','l','l','o','\0'} 
printf("%s",str); 

打印: 你好

如果字符串中的最后一个字符不是NUL,它将在字符串(“hello”)后面打印95个垃圾字符,因为数组大小为100,编译器无法知道字符串结束的位置。

尽管第6个单元格的零位在大多数编译器中都以字符串结束,但您可以只设置“hello”字符串,它们将用零填充剩余的单元格,所以在两种情况下都可以。

+0

NUL(空字符的名称)和NULL(空指针字面)是不同种类的动物。 – alk

+0

我没有写他们是同一件事.. –