繁体   English   中英

C样式字符串,指针,数组

[英]C style strings, Pointers, arrays

我无法理解C风格的字符串是什么。 新年快乐

我所知道的:指针包含一个内存地址。 取消引用指针将为您提供该内存位置的数据。

int x = 50;
int* ptr = &x;    //pointer to an integer, holds memory address of x

cout << "&x: " << &x << endl;  //these two lines give the same output as expected
cout << "ptr: " << ptr << endl;

cout << "*ptr: " << dec << (*ptr) << endl;  //prints out decimal number 50
                                           //added dec, so the program doesnt 
                //continue to printout hexidecimal numbers like it did for the 
                 //the memory addresses above
cout << "&ptr: " << &ptr << endl;  //shows that a pointer, like any variable,
                                  //has its own memory address

现在我不明白(使用上面的内容作为我的困惑的来源):有多种方式来声明字符串。 我正在学习C ++,但你也可以使用C风格的字符串(很好理解,虽然不如C ++字符串)

C ++:

string intro = "Hello world!"; 
//the compiler will automatically add a null character, \0, so you don't have to
//worry about declaring an array and putting a line into it that is bigger than 
//it can hold. 

C-风格:

char version1[7] = {'H','i',' ','y','o','u','\0'};
char version2[] = "Hi you"; //using quotes, don't need null character? added for you?
char* version3 = "Hi you";

版本3是我遇到麻烦的地方。 这里有一个指向char的指针。 我知道数组名是指向数组中第一个元素的指针。

cout << " &version3: " << &version3 << endl; //prints out location of 'H'
cout << " *version3: " << *version3 << endl; //prints out 'H'
cout << "  version3: " <<  version3 << endl; //prints out the whole string up to
                                             //automatically inserted \0

之前,在“我所知道的”部分中,打印出指针的名称会打印出它所持有的地址。 在这里,打印出指针的名称会打印出整个字符串。 围绕“嗨你”的双引号会以某种方式告诉程序:“嘿,我知道你是一个指针,你被初始化为'H'的位置,但因为我看到这些双引号,在内存位置向前跳过1个字节并打印出你看到的所有内容,直到达到\\ 0“(1字节移动,因为字符大1字节)。

如何打印出一个指针打印出一个字符串? 在打印出一个指针名称之前,打印出它被初始化为的内存地址。

编辑: cout << &version3是否打印出'H'的位置或指针的位置, version3 ,其中包含内存地址'H'?

使用cout打印char*工作方式与打印不同,例如,带有coutint* 为了与C风格的字符串兼容,带有char*参数的<<的重载版本将char*视为C风格的字符串。 如果要打印char*所持有的内存地址,可以将其转换为void*

是的,如果你写任何一个

char *s1 = "hi lol";
char s2[] = "hi haha";

在字符串的末尾为您添加NUL( \\0 )终结符。 这两者之间的区别在于s1是指向字符串文字的指针,根据C标准,您不应该修改内容,而s2是一个数组 ,即为您分配的内存块堆栈, 初始化为保存值"hi haha" ,您可以随意修改其内容。 为数组分配的内存量足以保存用作初始化程序的字符串,并自动为您确定,这就是方括号可以为空的原因。

一面注意:在C中,如果输入char s[3] = "abc"; ,然后s将初始化为{'a', 'b', 'c'}没有 NUL终止符! 这是因为标准中的一个子句说如果数组中有空间 (或类似的措辞),则使用NUL终结符初始化此上下文中的字符串。 在C ++中,情况并非如此。 有关更多信息,请参阅初始化固定大小的char数组时没有编译器错误,但没有足够的空间用于null终止符

编辑,以回应您添加的问题:如果您有char *s = "..." ,并且你cout << &s; ,它将打印存储指针 s的地址,而不是s保存的地址( s引用的字符串的第一个元素的地址)。

我知道数组名是指向数组中第一个元素的指针。

不,不是。 它只会隐式转换为一个(在大多数情况下)。

围绕“嗨你”的双引号会以某种方式告诉程序:“嘿,我知道你是一个指针,你被初始化为'H'的位置,但因为我看到这些双引号,在内存位置向前跳过1个字节打印出你看到的一切,直到你达到\\ 0“?

不,他们没有。 这是重要的类型。

std::ostream::operator<<具有用于通用指针的过载( void *过载const char * 所以当你写cout << "some char array or pointer"; ,它将调用该重载,而不是其他指针类型的重载。 这种重载的行为有所不同:它不是打印指针的数值,而是打印出所有内容,直到NUL终止符。

你在这里问两个问题,其中一个问题比较笼统,我将首先回答。

指针是指向内存中某个位置的“句柄”(称为地址)。 该位置的内容是一个值。 如何解释该值取决于指针的“类型”。 可以这样想:地址是房子的位置,例如10 Main Street。 10 Main Street的内容是该地址的房子内容。 在C(和C ++)术语中:

int *p;

是一个可以保存整数地址的变量。

int x;

是一个整数的变量。

p = &x;

通过在p中存储x的ADDRESS,p'指向'x。

x = 10;

在x中存储值10。

*p == x

因为* p表示'使用p'的内容作为值,然后将其与x进行比较。

p == &x

因为&x表示'使用x的地址'作为值,然后将其与p进行比较,p是类型指针的变量。

字符串是零个或多个字符的序列,在C(和C ++)中用字符“和”表示。 在内存中,这些值是连续存储的,并由一个尾随的空字节自动终止,该字节是一个值为0的字节。字符串“Hello,world!” 假设您使用的是8位ASCII字符编码,则存储在内存中,如下所示:

65 101 108 108 111 44​​ 32 87 111 114 108 33 0

您可以使用以下代码段自行查看:

char *p = "Hello, World!";
int len = strlen(p);
int i;

for (i = 0; i <= len;  ++i)
{
    std::cout << std::dec << (int) p[i] << ' ';
}
std::cout << std::endl;

由于null(零字节)由编译器自动添加到常量字符串,因此以下两个数组的大小相同:

char a1[7] = { 'H', 'i', ' ', 'y', 'o', 'u', '\0' };
char a2[] = "Hi you";

std::cout << strcmp(a1, a2) << std::endl

简单地说,'C样式字符串'只是一个以null结尾的字符数组,它可以回答您的第一个问题。

暂无
暂无

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

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