c++ 指针与数组

来源:互联网 发布:mysql countdistinct 编辑:程序博客网 时间:2024/05/16 14:10
[cpp] view plaincopy
  1. int *ip = new int;  
  2.     char s[] = "abcd";  
  3.     char* p = "abcd";  
  4.       
  5.     cout<<ip<<endl;  
  6.     cout<<*ip<<endl;  
  7.     cout<<&ip<<endl;  
  8. //    s = p; //error C2440: '=' : cannot convert from 'char *' to 'char'  
  9.                 //难道s不是指向第一个字符的指针吗?  
  10.     cout << s <<endl;//果然这句话输出的是abcd!  
  11.     cout << *s <<endl;//但这句输出的是a!  
  12.     cout << &s <<endl;  
  13.     cout << (s+1) <<endl;  
  14. //    cout << &(s+1) <<endl;//error C2102: '&' requires l-value  
  15.     cout << *(s+1) <<endl;  
  16.     cout << &s[1] <<endl;  
  17.   
  18.     cout << p <<endl;  
  19.     cout << *p <<endl;  
  20.     cout << &p <<endl;  
  21.     cout << (p+1) <<endl;  
  22. //    cout << &(p+1) <<endl;//error C2102: '&' requires l-value  
  23.     cout << *(p+1) <<endl;  
  24.     cout << &p[1] <<endl;  

输出:


相关解释:

char[]是一个数组定义,char*是指针定义,你可以看下他们的区别,对你会有帮助。
1 指针和数组的区别

(1)指针和数组的分配

  数组是开辟一块连续的内存空间,数组本身的标识符(也就是通常所说的数组名)代表整个数组,可以使用sizeof来获得数组所占据内存空间的大小(注意,不是数组元素的个数,而是数组占据内存空间的大小,这是以字节为单位的)。举例如下:
 
#include <stdio.h>

int main(void)
{
  char a[] = "hello";
  int b[] = {1, 2, 3, 4, 5};

  printf("a: %d\n", sizeof(a));
  printf("b memory size: %d bytes\n", sizeof(b));
  printf("b elements: %d\n", sizeof(b)/sizeof(int));

  return 0;
}
 

  
  数组a为字符型,后面的字符串实际上占据6个字节空间(注意最后有一个\0标识字符串的结束)。从后面sizeof(b)就可以看出如何获得数组占据的内存空间,如何获得数组的元素数目。至于int数据类型分配内存空间的多少,则是编译器相关的。gcc默认为int类型分配4个字节的内存空间。
 
(2)空间的分配

  这里又分为两种情况。

  第一,如果是全局的和静态的
  char *p = “hello”;
  这是定义了一个指针,指向rodata section里面的“hello”,可以被编译器放到字符串池。在汇编里面的关键字为.ltorg。意思就是在字符串池里的字符串是可以共享的,这也是编译器优化的一个措施。
  char a[] = “hello”;
  这是定义了一个数组,分配在可写数据块,不会被放到字符串池。

  第二,如果是局部的
  char *p = “hello”;
  这是定义了一个指针,指向rodata section里面的“hello”,可以被编译器放到字符串池。在汇编里面的关键字为.ltorg。意思就是在字符串池里的字符串是可以共享的,这也是编译器优化的一个措施。另外,在函数中可以返回它的地址,也就是说,指针是局部变量,但是它指向的内容是全局的。
  char a[] = “hello”;
  这是定义了一个数组,分配在堆栈上,初始化由编译器进行。(短的时候直接用指令填充,长的时候就从全局字符串表拷贝),不会被放到字符串池(同样如前,可能会从字符串池中拷贝过来)。注意不应该返回它的地址。


cout经研究得出以下结论:
1、对于数字指针如int *p=new int; 那么cout<<p只会输出这个指针的值,而不会输出这个指针指向的内容。
2、对于字符指针入char *p="sdf f";那么cout<<p就会输出指针指向的数据,即sdf f

============================================================================

如果还不是很理解,水木上也有高人对此进行解释:

这里的char ch[]="abc";表示ch 是一个足以存放字符串初值和空字符'/0'的一维数组,可以更改数组中的字符,但是char本身是不可改变的常量。char *pch = "abc";那么pch 是一个指针,其初值指向一个字符串常量,之后它可以指向其他位置,但如果试图修改字符串的内容,结果将不确定。     ______           ______      ______ch: |abc\0 |    pch: | ◎----->  |abc\0 |     ______           ______      ______char chArray[100];chArray[i] 等价于 *(chArray+i)和指针的不同在于   chArray不是变量   无法对之赋值另   事实上 i[chArray]  也等价于 *(chArray+i)


因此,总结如下:

1. char[] p表示p是一个数组指针,相当于const pointer,不允许对该指针进行修改。但该指针所指向的数组内容,是分配在栈上面的,是可以修改的。

2. char * pp表示pp是一个可变指针,允许对其进行修改,即可以指向其他地方,如pp = p也是可以的。对于*pp = "abc";这样的情况,由于编译器优化,一般都会将abc存放在常量区域内,然后pp指针是局部变量,存放在栈中,因此,在函数返回中,允许返回该地址(实际上指向一个常量地址,字符串常量区);而,char[] p是局部变量,当函数结束,存在栈中的数组内容均被销毁,因此返回p地址是不允许的。


同时,从上面的例子可以看出,cout确实存在一些规律:

1、对于数字指针如int *p=new int; 那么cout<<p只会输出这个指针的值,而不会输出这个指针指向的内容。
2、对于字符指针入char *p="sdf f";那么cout<<p就会输出指针指向的数据,即sdf f

那么,像&(p+1),由于p+1指向的是一个地址,不是一个指针,无法进行取址操作。

&p[1] = &p + 1,这样取到的实际上是从p+1开始的字符串内容。


分析上面的程序:

*pp = "abc";

p[] = "abc";

*pp指向的是字符串中的第一个字符。

cout << pp; // 返回pp地址开始的字符串:abc

cout << p; // 返回p地址开始的字符串:abc

cout << *p; // 返回第一个字符:a

cout << *(p+1); // 返回第二个字符:b

cout << &p[1];// 返回从第二个字符开始的字符串:bc


0 0
原创粉丝点击