关于字符串长度、终止 NUL 等 [英] About string length, terminating NUL, etc

查看:29
本文介绍了关于字符串长度、终止 NUL 等的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在学习 C,我对字符数组和字符串之间的差异以及它们的工作方式感到困惑.

问题 1:

为什么源代码 1 和源代码 2 的结果有差异?

源代码1:

#include #include int main(void){char c[2]="嗨";printf("%d\n", strlen(c));//返回3(不是2!?)返回0;}

源代码2:

#include #include int main(void){char c[3]="嗨";printf("%d\n", strlen(c));//返回2(不是3!?)返回0;}

问题 2:

字符串变量与字符数组有何不同?如果有的话,如何使用允许存储 \0 的最小所需索引号来声明它们(请阅读下面的代码)?

char name[index] = "Mick";//索引应该是4还是5?字符名称[索引] = {'M', 'i', 'c', 'k'};//索引应该是4还是5?#define name "Mick"//尺寸是多少?有\0吗?

问题 3:

终止 NUL 是否仅跟随字符串而不跟随字符数组?那么字符串Hi"的实际值为[H][i][\0],而字符数组Hi"的实际值为[H][i]?

问题 4:

假设 c[2] 将存储Hi"后跟一个 \0(不确定这是如何完成的,也许使用 gets(c) ?).那么 \0 存储在哪里?它是存储在 c[2] 之后的某处"成为 [H][i]\0 还是将 c[2] 附加一个 \0 成为 c[3],即 [H][i][\0]?

当我通过 if (c1==c2) 比较两个变量时,有时在字符串/字符数组后面有一个 \0 会导致麻烦,因为它很可能返回 FALSE (0).

感谢详细的答案.但保持你的回答简短有助于我的理解:)提前谢谢你!

解决方案

问题 1:

为什么源码1和源码的结果有区别代码 2?

源代码1:

#include #include int main(){char c[2]="嗨";printf("%d", strlen(c));//返回3(不是2!?)获取字符();}

<块引用>

源代码2:

#include #include int main(){char c[3]="嗨";printf("%d", strlen(c));//返回2(不是3!?)获取字符();}

答案:因为在第一种情况下,c[] 只持有Hi".strlen 在末尾查找零,并且根据 c[] 后面的内容,迟早会找到零,或者崩溃.如果不确切知道 c[] 数组后面的内存中的内容,我们就不能说.

<块引用>

问题 2:

字符串变量与字符数组有何不同?如何申报它们具有允许存储 \0 的最小所需索引号如果有(请阅读下面的代码)?

char name[index] = "Mick";//索引应该是4还是5?字符名称[索引] = {'M', 'i', 'c', 'k'};//索引应该是4还是5?

回答真的取决于你想做什么.如果您想实际将内容用作字符串,则可能为 5.但是没有什么说你不能在一个 4 个字符的数组中存储Mick"——你只是不能使用 strlen 来找出它有多长,因为 strlen 将继续到 5 并且很可能(很多)进一步找到长度,如果接下来的几个内存位置没有零,可能会导致崩溃,因为最终将没有有效的内存地址可供读取.

#define name "Mick"//尺寸是多少?有\0吗?

这完全没有大小,除非您在某处使用名称.#defines 不是编译器所见的一部分 - 如果您在任何地方使用 name,预处理器会将 name 替换为 "Mick" - 并且希望这是编译器可以理解的地方.然后适用与先前答案相同的规则 - 这取决于您想如何使用字符数组.为了正确操作 strlenstrpy 和几乎所有其他 str... 函数,最后需要一个零.

<块引用>

问题 3:

终止空值是否只跟在字符串后面而不跟在字符数组后面?所以字符串 "Hi" 的实际值为 [H][i][\0] 并且实际值为字符数组 "Hi" 是 [H][i]?

是的,不,也许吧.这完全取决于您如何使用 "Hi" 字符串文字(这是双引号内的东西"的技术名称).如果编译器是允许的",它会在最后放一个零.但是如果你将一个数组初始化为给定的大小,它就会把字节塞进那里,如果没有空间可以容纳零,那是你的问题,而不是编译器的问题.

<块引用>

问题 4:

假设 c[2] 将存储Hi"后跟一个 \0(不确定如何这已经完成了,也许使用gets(c)?).那么 \0 存储在哪里?是吗存储在 c[2] 之后的某处"成为 [H][i]\0 或将 c[2]附加一个 \0 成为 c[3],即 [H][i][\0]?

在 c[2] 中,除了 'H'、'i' 之外,不知道存储了什么 [从技术上讲,它很可能是地球的尽头"——用计算机术语来说,那就是可以存储的内存"'t be read - 在这种情况下 strlen 将会使你的程序崩溃,因为 strlen 读取到地球的尽头].但如果也可以是零、一、字母a"、数字 42 或任何其他 8 位 [1] 值.

<块引用>

有时会在后面跟一个 \0 令人困惑字符串/字符数组,当我比较两个变量时会导致麻烦if (c1==c2) 因为它很可能返回 FALSE (0).

如果 c1 和 c2 是字符数组,那总是错误的,因为 c1 和 c2 永远不会有相同的地址,当以这种方式在 C 中使用数组时,它变成第一个在内存中的地址数组中的元素".所以无论c1和c2的内容是什么,它们的地址永远不会相同[因为它们是两个不同的变量,并且两个变量在内存中不能有相同的位置——这就像试图将两辆车停在一个停车位大到只能容纳一辆车——不,在我们的思想实验中不允许压碎任何一辆车].

[1] 字符不能保证为 8 位.但让我们暂时了解一下.

I'm currently learning C and I'm confused with differences between char array and string, as well as how they work.

Question 1:

Why is there a difference in the outcomes of source code 1 and source code 2?

Source code 1:

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

int main(void)
{
    char c[2]="Hi";
    printf("%d\n", strlen(c));   //returns 3 (not 2!?)
    return 0;
}

Source code 2:

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

int main(void)
{
    char c[3]="Hi";
    printf("%d\n", strlen(c));   //returns 2 (not 3!?)
    return 0;
}

Question 2:

How is a string variable different from a char array? How to declare them with the minimum required index numbers allowing \0 to be stored if any (please read the codes below)?

char name[index] = "Mick";   //should index be 4 or 5?

char name[index] = {'M', 'i', 'c', 'k'};   //should index be 4 or 5?

#define name "Mick"   //what is the size? Is there a \0?

Question 3:

Does the terminating NUL ONLY follow strings but not char arrays? So the actual value of the string "Hi" is [H][i][\0] and the actual value of the char array "Hi" is [H][i]?

Question 4:

Suppose c[2] is going to store "Hi" followed by a \0 (not sure how this is done, using gets(c) maybe?). So where is the \0 stored? Is it stored "somewhere" after c[2] to become [H][i]\0 or will c[2] be appended with a \0 to become c[3] which is [H][i][\0]?

It is quite confusing that sometimes there is a \0 following the string/char array and causes trouble when I compare two variables by if (c1==c2) as it most likely returns FALSE (0).

Detailed answers are appreciated. But keeping your answer brief helps my understanding :) Thank you in advance!

解决方案

Question 1:

Why is there a difference in the outcomes of source code 1 and source code 2?

Source code 1:

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

int main()
{
    char c[2]="Hi";
    printf("%d", strlen(c));   //returns 3 (not 2!?)
    getchar();
}

Source code 2:

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

int main()
{
    char c[3]="Hi";
    printf("%d", strlen(c));   //returns 2 (not 3!?)
    getchar();
}

answer: Because in the first case, c[] is only holding "Hi". strlen looks for a zero at the end, and, depending on exactly what is behind c[] finds one sooner or later, or crashes. We can't say without knowing exactly what is in the memory behind the c[] array.

Question 2:

How is a string variable different from a char array? How to declare them with the minimum required index numbers allowing \0 to be stored if any (please read the codes below)?

char name[index] = "Mick";   //should index be 4 or 5?

char name[index] = {'M', 'i', 'c', 'k'};   //should index be 4 or 5?

answer Really depends on what you want to do. Probably 5 if you want to actually use the content as a string. But there's nothing saying you can't store "Mick" in a 4 character array - you just can't use strlen to find out how long it is, because strlen will continue to 5 and quite possibly (much) further to find the length, and if there is no zero in the next several memory locations, it could lead to a crash, because eventually, there won't be valid memory addresses to read.

#define name "Mick" //what is the size? Is there a \0?

This has absolutely no size at all, until you use name somwhere. #defines are not part of what the compiler sees - the pre-processor will replace name with "Mick" if you use name anywhere - and hopefully, that's in a place the compiler can make sense of. And then the same rules apply as in previous answer - it depends on how you want to use the array of characters. For correct operation with strlen, strpy, and nearly all other str... functions, you need a zero at the end.

Question 3:

Does the terminating null ONLY follow strings but not char arrays? So the actual value of the string "Hi" is [H][i][\0] and the actual value of the char array "Hi" is [H][i]?

Yes, no, maybe. It all depends on how you USE the "Hi" string literal (that's the technical name for 'something within double quotes'). If the compiler is "allowed", it will put a zero at the end. But if you initialize an array to a given size, it will stuff the bytes in there, and if there isn't room for a zero, that's your problem, not the compiler's.

Question 4:

Suppose c[2] is going to store "Hi" followed by a \0 (not sure how this is done, using gets(c) maybe?). So where is the \0 stored? Is it stored "somewhere" after c[2] to become [H][i]\0 or will c[2] be appended with a \0 to become c[3] which is [H][i][\0]?

In c[2], beyond the 'H', 'i', there is no telling what is stored [technically, it could well be "the end of the earth" - in computer terms, that's "memory that can't be read - in which case strlen on that WILL crash your program, because strlen reads beyond the end of the earth]. But if could also be a zero, a one, the letter 'a', the number 42, or any other 8-bit [1] value.

It is quiet confusing that sometimes there is a \0 following the string/char array and causes trouble when I compare two variables by if (c1==c2) as it most likely returns FALSE (0).

If c1 and c2 are char arrays, that will ALWAYS be false since c1 and c2 are never going to have the same address, and when using an array in C in that way, it becomes "the address in memory of the first element in the array". So no matter what teh contents of c1 and c2 is, their address can never be the same [because they are two different variables, and two variables can not have the same location in memory - that's like trying to park two cars in a parking space large enough only for one car - and no, crushing either car is not allowed in our thought experiment].

[1] Char isn't guaranteed to be 8 bits. But lets inore that for now.

这篇关于关于字符串长度、终止 NUL 等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆