关于C指针和字符串问题 [英] Question about pointers and strings in C

查看:143
本文介绍了关于C指针和字符串问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


  

可能重复:结果
  <一href=\"http://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s-in-c\">What是个char []和char * S用C?结果之间的差异
  <一href=\"http://stackoverflow.com/questions/12121759/difference-between-char-str-and-char-strn\">Difference字符之间*海峡=...和char海峡[N] =...?


我有有一些code让我不解。

 的#include&LT;&stdio.h中GT;
#包括LT&;&stdlib.h中GT;INT主(INT ARGC,CHAR *的argv [])
{
  字符*字符串1 =这是一个测试;
  字符字符串2 [] =这是一个测试;
  的printf(%I,%I \\ N的sizeof(字符串1)的sizeof(字符串2));
  系统(暂停);
  返回0;
}

当它输出字符串1的大小,它打印4,这是可以预料的,因为指针的大小为4字节。但是,当它打印字符串2,它输出15.我认为,一个数组是一个指针,所以字符串2的大小应该是相同的字符串1吧?那么,为什么它打印出两种不同尺寸的相同类型的数据(指针)?


解决方案

数组和指针是完全不同的动物。在大多数情况下,一个的前pression 的指定数组被视为指针。

首先,一点点的标准语言( n1256


6.3.2.1左值,数组和功能代号的结果
...结果
3除非它是的sizeof 运营商或一元运营商的操作数或者是一个字符串字面来初始化数组,具有类型转换为一个前pression,类型为指针键入这点键入阵列一个前pression到数组对象,初始元素不是一个左值。如果数组对象有注册存储类,行为是不确定的。结果

字符串这是一个测试字符的有15个元素的数组。在报关搜索结果

 
    字符*字符串1 =这是一个测试;

结果
字符串1 被声明为指针,以字符。按照上述语言,的前pression类型的这是一个测试从的char [15] 转换为的char * ,并将得到的指针值赋给字符串1 。结果
搜索结果
在宣言
搜索结果

 
    字符字符串2 [] =这是一个测试;

结果
不同的东西发生。更多的标准语言:
搜索结果


6.7.8初始化的结果
...结果
14字符类型的阵列可以由一个字符串被初始化文字,任选
大括号括起来。字符串字面量连续的字符(包括
终止空字符,如果有房间或如果阵列是未知大小的)初始化数组的元素。结果
...结果
22如果未知大小的数组初始化,其大小由带有明确初始化最大的索引元素决定。在它的初始化列表的末尾,数组不再有不完整的类型。

在这种情况下,字符串2 被声明为字符的数组,其大小是从长度计算初始化和字符串的的内容的被复制到阵列。

下面是一个假设性的存储器映射来说明发生了什么:
结果


项目地址为0x00为0x01 0X02×03
---- ------- ---- ---- ---- ----
没有名字的0x08001230'T'H''我''S'
              0x08001234'''我''S'''
              0x08001238'A''''T''E'
              0x0800123C'S''T'0
              ...
字符串1 0x12340000 0x08的0×00 0×12的0x30
字符串2 0x12340004'T''H''我''S'
              0x12340008'''我''S'''
              0x1234000C'A''''T''E'
              0x1234000F的'T'0

字符串常量有静态的程度;也就是说,对他们的内存在程序启动时预留并保持到程序终止。试图修改字符串的内容调用未定义的行为;底层平台可以或可以不允许的话,和标准的地方上的编译器没有任何限制。这是最好的作为,虽然文字总是不可写。

在我上面的内存映射,该字符串的地址从字符串1 的地址和字符串2 来说明这一点。

无论如何,你可以看到字符串1 ,有一个指针类型,包含的地址字符串的的。 字符串2 ,作为一个数组类型,包含的字符串的的内容的复印件。

由于字符串2 在编译时是已知的,的sizeof 返回的大小(字节数)的大小的阵列。

%I 转换操作符不使用类型的前pressions 为size_t 是正确的。如果你在工作的C99,使用%祖。在C89,你可以使用鲁%和施放前pression到无符号长
结果

 
C89:输出(%禄,禄%\\ n,(无符号长)的sizeof字符串1,(无符号长)的sizeof字符串2);
C99:输出(%祖,祖%\\ n,sizeof的字符串1,sizeof的字符串2);

注意的sizeof 运营商的,而不是一个函数调用;当操作数是表示的对象的前pression 的,括号内是没有必要的(虽然他们不伤害)。

Possible Duplicate:
What is the difference between char s[] and char *s in C?
Difference between char *str = "…" and char str[N] = "…"?

I have some code that has had me puzzled.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  char* string1 = "this is a test";
  char string2[] = "this is a test";
  printf("%i, %i\n", sizeof(string1), sizeof(string2));
  system("PAUSE"); 
  return 0;
}

When it outputs the size of string1, it prints 4, which is to be expected because the size of a pointer is 4 bytes. But when it prints string2, it outputs 15. I thought that an array was a pointer, so the size of string2 should be the same as string1 right? So why is it that it prints out two different sizes for the same type of data (pointer)?

解决方案

Arrays and pointers are completely different animals. In most contexts, an expression designating an array is treated as a pointer.

First, a little standard language (n1256):

6.3.2.1 Lvalues, arrays, and function designators
...
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

The string literal "this is a test" is a 15-element array of char. In the declaration


    char *string1 = "this is a test";


string1 is being declared as a pointer to char. Per the language above, the type of the expression "this is a test" is converted from char [15] to char *, and the resulting pointer value is assigned to string1.


In the declaration


    char string2[] = "this is a test";


something different happens. More standard language:

6.7.8 Initialization
...
14 An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.
...
22 If an array of unknown size is initialized, its size is determined by the largest indexed element with an explicit initializer. At the end of its initializer list, the array no longer has incomplete type.

In this case, string2 is being declared as an array of char, its size is computed from the length of the initializer, and the contents of the string literal are copied to the array.

Here's a hypothetical memory map to illustrate what's happening:

Item          Address       0x00  0x01  0x02  0x03
----          -------       ----  ----  ----  ----
no name       0x08001230    't'   'h'   'i'   's'
              0x08001234    ' '   'i'   's'   ' '
              0x08001238    'a'   ' '   't'   'e'
              0x0800123C    's'   't'    0
              ...
string1       0x12340000    0x08  0x00  0x12  0x30
string2       0x12340004    't'   'h'   'i'   's'
              0x12340008    ' '   'i'   's'   ' '
              0x1234000C    'a'   ' '   't'   'e'
              0x1234000F    's'   't'    0

String literals have static extent; that is, the memory for them is set aside at program startup and held until the program terminates. Attempting to modify the contents of a string literal invokes undefined behavior; the underlying platform may or may not allow it, and the standard places no restrictions on the compiler. It's best to act as though literals are always unwritable.

In my memory map above, the address of the string literal is set off somewhat from the addresses of string1 and string2 to illustrate this.

Anyway, you can see that string1, having a pointer type, contains the address of the string literal. string2, being an array type, contains a copy of the contents of the string literal.

Since the size of string2 is known at compile time, sizeof returns the size (number of bytes) in the array.

The %i conversion specifier is not the right one to use for expressions of type size_t. If you're working in C99, use %zu. In C89, you would use %lu and cast the expression to unsigned long:


C89: printf("%lu, %lu\n", (unsigned long) sizeof string1, (unsigned long) sizeof string2);
C99: printf("%zu, %zu\n", sizeof string1, sizeof string2);

Note that sizeof is an operator, not a function call; when the operand is an expression that denotes an object, parentheses aren't necessary (although they don't hurt).

这篇关于关于C指针和字符串问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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