C 中的数组和空字符
Array in C and null character
我正在做 Brian W. Kernighan 和 Dennis M. Ritchie 在 "The C Programming Language" 一书中提出的关于数组的练习。
该练习需要一个能够接收文本行作为输入并显示超过 80 个字符的程序。为了方便起见,我在这里定义了最多 3 条输入线,20 条作为最大长度,5 条作为显示的边界。
程序运行良好,"printValues" 函数允许我查看哪些插入行超过 5 个字符,但我的好奇心促使我查看空字符 (/ 0) 是否确实放置在未使用的空格中的载体。
令我惊讶的是,输出是多种多样的;如果我使用这样的输入:
one
two
helloworld
第一行的输出将是:
nomi[0][0]=o
nomi[0][1]=n
nomi[0][2]=e
nomi[0][3]=[=11=]
nomi[0][4]=?
nomi[0][5]=
nomi[0][6]=[=11=]
nomi[0][7]=[=11=]
nomi[0][8]=[=11=]
nomi[0][9]=?
nomi[0][10]=c
nomi[0][11]=
nomi[0][12]=
nomi[0][13]=[=11=]
nomi[0][14]=[=11=]
nomi[0][15]=[=11=]
nomi[0][16]=
nomi[0][17]=[=11=]
nomi[0][18]=[=11=]
nomi[0][19]=[=11=]
nomi[1][0]=t
nomi[1][1]=w
nomi[1][2]=o
nomi[1][3]=[=11=]
nomi[1][4]=[=11=]
nomi[1][5]=[=11=]
nomi[1][6]=[=11=]
nomi[1][7]=[=11=]
nomi[1][8]=[=11=]
nomi[1][9]=[=11=]
nomi[1][10]=[=11=]
nomi[1][11]=[=11=]
nomi[1][12]=[=11=]
nomi[1][13]=[=11=]
nomi[1][14]=[=11=]
nomi[1][15]=[=11=]
nomi[1][16]=[=11=]
nomi[1][17]=[=11=]
nomi[1][18]=[=11=]
nomi[1][19]=[=11=]
nomi[2][0]=h
nomi[2][1]=e
nomi[2][2]=l
nomi[2][3]=l
nomi[2][4]=o
nomi[2][5]=w
nomi[2][6]=o
nomi[2][7]=r
nomi[2][8]=d
nomi[2][9]=[=11=]
nomi[2][10]=[=11=]
nomi[2][11]=[=11=]
nomi[2][12]=[=11=]
nomi[2][13]=[=11=]
nomi[2][14]=[=11=]
nomi[2][15]=[=11=]
nomi[2][16]=[=11=]
nomi[2][17]=[=11=]
nomi[2][18]=[=11=]
nomi[2][19]=[=11=]
进行一些测试后,我意识到只有在第一行中,矢量的空单元格中才会出现一些奇怪的字符。
有人可以给我解释一下吗?
对不起我的英语。
#include <stdio.h>
#define MAXNAMES 3
#define MAXNAMESLENGHT 20
#define HIGHERTHAN 5
void printValues(char names[][MAXNAMESLENGHT], char provisionalName[]);
void printIndexs(char names[][MAXNAMESLENGHT]);
int main() {
char names[MAXNAMES][MAXNAMESLENGHT];
char provisionalName[MAXNAMESLENGHT];
int i, e, c;
for(i = 0; i <= MAXNAMES - 1; i++) {
for(e = 0; e <= (MAXNAMESLENGHT - 2) && (c = getchar()) != EOF && c != '\n'; ++e) {
names[i][e] = c;
}
names[i][e] = '[=12=]';
}
printValues(names, provisionalName);
printIndexs(names);
return 0;
}
void printValues(char names[][MAXNAMESLENGHT], char provisionalName[]) {
printf("________________________________________");
printf("\nI nomi che superano i %d caratteri sono:\n", HIGHERTHAN);
int i, e;
char flag = 'F';
for(i = 0; i <= MAXNAMES - 1; ++i) {
for(e = 0; e <= MAXNAMESLENGHT - 1 && names[i][e] != '[=12=]'; ++e)
provisionalName[e] = names[i][e];
provisionalName[e] = '[=12=]';
if(e > HIGHERTHAN) {
flag = 'T';
printf("%s\n", provisionalName);
}
}
if(flag == 'F') printf("nessuno\n");
}
void printIndexs(char names[][MAXNAMESLENGHT]) {
printf("________________________________________");
printf("\nIndici:\n");
for(int i = 0; i <= MAXNAMES - 1; ++i) {
for(int e = 0; e <= MAXNAMESLENGHT - 1; ++e) {
if(names[i][e] == '\n') // return (\n)
printf("names[%d][%d]=\n\n", i, e);
else if(names[i][e] == '[=12=]') // null character ([=12=])
printf("names[%d][%d]=\0\n", i, e);
else
printf("names[%d][%d]=%c\n", i, e, names[i][e]); // carattere
}
printf("\n");
}
printf("\n");
}
在没有像 static
这样的限定符的函数内部定义的对象不会自动初始化。 (您的数组是对象。)通常,编译器对此类对象使用 stack(但除了简单地使用堆栈之外,它们可能会使用处理器寄存器并进行各种优化)。您在该区域中看到的数据仅仅是之前使用堆栈的剩余数据。 (虽然 main
是您的 C 程序中执行的第一个例程,但在 main
之前实际执行了启动代码,为您的程序设置 C 环境。它在堆栈上留下了一些数据。 )
数组的元素永远不会“空”。对于 char
对象,C 没有表示“空”的值。1 C 不会自动将您的数组初始化为“空”或在其元素中具有零值。当你定义数组时,你得到的只是保证有你可以访问的存储——你没有得到关于该存储中的内容的任何保证。
脚注
1 C的语义比较复杂,存在对象的值未指定的情况,这不仅意味着它的值不是由规则决定的C 但程序可能表现得好像对象没有固定值(每次使用它时它可能看起来不同)。
我正在做 Brian W. Kernighan 和 Dennis M. Ritchie 在 "The C Programming Language" 一书中提出的关于数组的练习。 该练习需要一个能够接收文本行作为输入并显示超过 80 个字符的程序。为了方便起见,我在这里定义了最多 3 条输入线,20 条作为最大长度,5 条作为显示的边界。
程序运行良好,"printValues" 函数允许我查看哪些插入行超过 5 个字符,但我的好奇心促使我查看空字符 (/ 0) 是否确实放置在未使用的空格中的载体。 令我惊讶的是,输出是多种多样的;如果我使用这样的输入:
one
two
helloworld
第一行的输出将是:
nomi[0][0]=o
nomi[0][1]=n
nomi[0][2]=e
nomi[0][3]=[=11=]
nomi[0][4]=?
nomi[0][5]=
nomi[0][6]=[=11=]
nomi[0][7]=[=11=]
nomi[0][8]=[=11=]
nomi[0][9]=?
nomi[0][10]=c
nomi[0][11]=
nomi[0][12]=
nomi[0][13]=[=11=]
nomi[0][14]=[=11=]
nomi[0][15]=[=11=]
nomi[0][16]=
nomi[0][17]=[=11=]
nomi[0][18]=[=11=]
nomi[0][19]=[=11=]
nomi[1][0]=t
nomi[1][1]=w
nomi[1][2]=o
nomi[1][3]=[=11=]
nomi[1][4]=[=11=]
nomi[1][5]=[=11=]
nomi[1][6]=[=11=]
nomi[1][7]=[=11=]
nomi[1][8]=[=11=]
nomi[1][9]=[=11=]
nomi[1][10]=[=11=]
nomi[1][11]=[=11=]
nomi[1][12]=[=11=]
nomi[1][13]=[=11=]
nomi[1][14]=[=11=]
nomi[1][15]=[=11=]
nomi[1][16]=[=11=]
nomi[1][17]=[=11=]
nomi[1][18]=[=11=]
nomi[1][19]=[=11=]
nomi[2][0]=h
nomi[2][1]=e
nomi[2][2]=l
nomi[2][3]=l
nomi[2][4]=o
nomi[2][5]=w
nomi[2][6]=o
nomi[2][7]=r
nomi[2][8]=d
nomi[2][9]=[=11=]
nomi[2][10]=[=11=]
nomi[2][11]=[=11=]
nomi[2][12]=[=11=]
nomi[2][13]=[=11=]
nomi[2][14]=[=11=]
nomi[2][15]=[=11=]
nomi[2][16]=[=11=]
nomi[2][17]=[=11=]
nomi[2][18]=[=11=]
nomi[2][19]=[=11=]
进行一些测试后,我意识到只有在第一行中,矢量的空单元格中才会出现一些奇怪的字符。 有人可以给我解释一下吗?
对不起我的英语。
#include <stdio.h>
#define MAXNAMES 3
#define MAXNAMESLENGHT 20
#define HIGHERTHAN 5
void printValues(char names[][MAXNAMESLENGHT], char provisionalName[]);
void printIndexs(char names[][MAXNAMESLENGHT]);
int main() {
char names[MAXNAMES][MAXNAMESLENGHT];
char provisionalName[MAXNAMESLENGHT];
int i, e, c;
for(i = 0; i <= MAXNAMES - 1; i++) {
for(e = 0; e <= (MAXNAMESLENGHT - 2) && (c = getchar()) != EOF && c != '\n'; ++e) {
names[i][e] = c;
}
names[i][e] = '[=12=]';
}
printValues(names, provisionalName);
printIndexs(names);
return 0;
}
void printValues(char names[][MAXNAMESLENGHT], char provisionalName[]) {
printf("________________________________________");
printf("\nI nomi che superano i %d caratteri sono:\n", HIGHERTHAN);
int i, e;
char flag = 'F';
for(i = 0; i <= MAXNAMES - 1; ++i) {
for(e = 0; e <= MAXNAMESLENGHT - 1 && names[i][e] != '[=12=]'; ++e)
provisionalName[e] = names[i][e];
provisionalName[e] = '[=12=]';
if(e > HIGHERTHAN) {
flag = 'T';
printf("%s\n", provisionalName);
}
}
if(flag == 'F') printf("nessuno\n");
}
void printIndexs(char names[][MAXNAMESLENGHT]) {
printf("________________________________________");
printf("\nIndici:\n");
for(int i = 0; i <= MAXNAMES - 1; ++i) {
for(int e = 0; e <= MAXNAMESLENGHT - 1; ++e) {
if(names[i][e] == '\n') // return (\n)
printf("names[%d][%d]=\n\n", i, e);
else if(names[i][e] == '[=12=]') // null character ([=12=])
printf("names[%d][%d]=\0\n", i, e);
else
printf("names[%d][%d]=%c\n", i, e, names[i][e]); // carattere
}
printf("\n");
}
printf("\n");
}
在没有像 static
这样的限定符的函数内部定义的对象不会自动初始化。 (您的数组是对象。)通常,编译器对此类对象使用 stack(但除了简单地使用堆栈之外,它们可能会使用处理器寄存器并进行各种优化)。您在该区域中看到的数据仅仅是之前使用堆栈的剩余数据。 (虽然 main
是您的 C 程序中执行的第一个例程,但在 main
之前实际执行了启动代码,为您的程序设置 C 环境。它在堆栈上留下了一些数据。 )
数组的元素永远不会“空”。对于 char
对象,C 没有表示“空”的值。1 C 不会自动将您的数组初始化为“空”或在其元素中具有零值。当你定义数组时,你得到的只是保证有你可以访问的存储——你没有得到关于该存储中的内容的任何保证。
脚注
1 C的语义比较复杂,存在对象的值未指定的情况,这不仅意味着它的值不是由规则决定的C 但程序可能表现得好像对象没有固定值(每次使用它时它可能看起来不同)。