따라서 의도적으로 다시 물건 포인터와 배열, 비교적 간단한 다른 유형의 배열로 탐구, C 언어 포인터의 유연성으로 인해, 선두 포인터는 배열의 사용을 대체 할 수있는, 또는 조합이 포인터와 배열의 많은 혼란을 주도 문자 포인터와이 두 가지의 캐릭터의 혼란 배열입니다. . . 다음은이 두 가지 고통과 슬픔 무엇인지를 분석하기 시작했다. . .
자연 1 개 어레이
배열 요소의 복수의 집합이고, 상기 메모리 유닛의 어드레스에 연결된 분배 장치는 첨자 다른 요소들에 의해 액세스 될 수있다. .
2 포인터.
또한 포인터 변수가 있지만,이 메모리 셀에 저장되고, 다른 위치에 어드레스를 식별한다. . 주소가 정수, 32 비트 플랫폼이기 때문에, 기본 32 비트 포인터이다. .
3 포인터?
소수점 데이터 유형은 직접 다른 유닛 어드레스 포인터 변수 저장 부에 저장된 것을 의미한다.
INT P * // 메모리 단위 어드레스에 저장되는 데이터의 P 형이있는 변수는 정수이고
* Q를 떠; // ........................................ 플로트
이 주소를 저장하기 때문에 관계없이 그 데이터 포인트의 종류, 포인터 변수 자체는 항상 정수입니다.
4 문자 배열. . .
그대로 배열 수단, 배열 요소의 문자들이다. . 사실,이 본질적인 의미입니다.
숯 STR [10];
그것은 10 개 요소와 요소 유형의 문자 배열을 정의합니다.
언제 C 언어로 정의 된 변수를 초기화 할 수 있습니다.
숯 STR [10] = { "안녕하세요"};
컴파일러는 구문 만나면 배열 안녕하세요 \ 0 의해 제 소자로부터 str에 기입한다. .
C 언어는 실제 문자열 형식이 없기 때문에이 요소가 연속 해결할 수 있기 때문에, 그것은 문자의 문자열 배열로 나타낼 수있다, 그것은 충분했다.
C 언어 어레이는 제 어드레스 [0] 어드레스, 즉 STR STR 소정 메모리 위치의 어레이를 나타낸다 STR = [0];
의 printf ( "%의 S", STR) 왜 제 주소 문자열을 출력 할 수있다. .
자연 상수 C 언어 문자열에 키가 있기 때문에 훨씬 더 어려운 초보자의 문제를 이해하는 것입니다 주소의 표현은 사실이다. . .
예를 들면 :
* CHAR S;
S = "중국";
왜 당신은 문자열 포인터 변수를 할당 할 수 있습니다. .
이 불일치 그것의 형식이 아닙니다? ? ?
이것은 위에서 언급 한 키입니다. .
C 언어 컴파일러는 "중국"의 경우,은 0x3000 0x3001 0x3002 0x3003 0x3004 함 0x3005의 메모리에 주소 문자열 상수 지정합니다.
S = "중국", 무슨 의식, 그래, 주소.
사실, S의 진정한 의미 = "중국"=은 0x3000;
이 봐, 당신은 중국이 문자열로 간주하는 듯했으나 컴파일러 주소은 0x3000으로 볼, 즉 문자열 상수의 성능의 본질이다의 첫 번째 문자의 주소의 대표입니다. . . . . . . . . .
S =은 0x3000
쓰기는 직관적 인 의미에 맞춰 더 많은 것 같다. . .
이 문제를 이해합니다. .
그래서 %들, 그 원리는 실제로 출력 문자열의 printf ( "% s '에,들) 문자열로 첫 번째 주소입니다 실제로 전달이 문자열의 저장의 주소입니다. . .
등
#INCLUDE <STDIO.H>
) (대표 값 int
{
* CHAR S;
S = "안녕하세요";
의 printf ( "% P \ 없음", S);
0을 반환;
}
중국 ""첫 번째 주소 인,의의 =의 0x00422020 참조
따라서,의 printf ( "%의 S"0x00422020)도 동등한. .
문자의 배열 :
숯 STR [10] = "안녕하세요";
이미 말한 것처럼, STR STR = [0], 제 주소 "안녕하세요"와 동등하다. .
그러므로의 printf ( "%의 S", STR)도 본질적으로는 printf ( "% S의"주소 ");
C 언어 스트링 작업은 최종 문자열의 본질은, 메모리 셀에 저장되어있는 선두 어드레스에 의해 수행된다. . .
5 char * 부여 char a [];
* CHAR S;
[η]는 char;
스트링의 이전에 제 1 어드레스 대표 언급이 포인터의 주소 문자열도 (사실, 선두 어드레스)에 저장되는 경우, 즉 첫 번째 문자의 주소,이 어드레스 데이터는 문자 단위
이것은 또한의 지적 문자와 일치합니다.
따라서 S는 A =;
그러나이 아니라 = s의;
배열 이름 포인터에 복사 할 수 C 언어 어드레스를 나타내고 있지만,이 어레이 이름에 할당 될 수없고, 그 일정 유형이며, 이는 변경 될 수 없다. .
물론이 될 수있다 :
A [] = "안녕하세요"를 숯불;
* CHAR는 A = S;
for(int i= 0; i < strlen(a) ; i++)
printf("%c", s[i]);
或 printf("%c",*s++);
字符指针可以用 间接操作符 *取其内容,也可以用数组的下标形式 [ ],数组名也可以用 *操作,因为它本身表示一个地址 。。
比如 printf("%c",*a); 将会打印出 'h'
char * 与 char a[ ] 的本质区别:
当定义 char a[10 ] 时,编译器会给数组分配十个单元,每个单元的数据类型为字符。。
而定义 char *s 时, 这是个指针变量,只占四个字节,32位,用来保存一个地址。。
sizeof(a) = 10 ;
sizeof(s) = ?
当然是4了,编译器分配4个字节32位的空间,这个空间中将要保存地址。。。
printf("%p",s);
这个表示 s 的单元中所保存的地址。。
printf("%p",&s);
这个表示变量本身所在内存单元地址。。。。,不要搞混了。。
用一句话来概括,就是 char *s 只是一个保存字符串首地址的指针变量, char a[ ] 是许多连续的内存单元,单元中的元素为char ,之所以用 char *能达到
char a [ ] 的效果,还是字符串的本质,地址,即给你一个字符串地址,便可以随心所欲的操所他。。但是,char* 和 char a[ ] 的本质属性是不一样的。。
6 char ** 与char * a[ ] ;
先看 char *a [ ] ;
[] 때문에하는 *] 결합하여 상기 제 1 및보다 높은 우선 순위, 그 배열의 요소의 배열 어드레스를 저장 숯 * 숯 *가 가변 앞에서 설명한하였습니다. .
所以 문자 *는 [] = { "중국", "프랑스어", "미국", "독일어"};
같은 문구를 볼 수있는 동안, 배열 요소는,는 sizeof (a)는 얼마나 많은 사람들이 생각하는 다섯 개 단어 6 + 7 + 8 + 7 = 28의 메모리의 총 바이트 수를 설명하는 문자열입니다 ;
그러나, 실제로는 sizeof는 (a) = 16;
이미 말한 것처럼 이유 문자열 상수의 본질은 해결하는 배열 요소 포인터 * 4 바이트이므로 4 개 요소 포인터 변수 총 16 바이트 숯불
예를 들어 봐 :
#INCLUDE <STDIO.H>
INT 주 ()
{
문자 *는 [] = { "중국", "프랑스어", "미국", "독일어"};
의 printf ( "%의 P %의 P %의 P % 포인트 \ n을"A [0], A [1], A [2], A [3]);
0을 반환;
}
어레이가 아닌 문자열 문자열 자체의 처음 주소 네에서 4 개 개의 주소를 나타내는 네 개의 메모리 주소를 담고에서는 4 개 요소를 볼 수있다. . .
따라서는 sizeof (a) 과정 (16). .
注意这四个地址是不连续的,它是编译器为"China","French","America","German" 分配的内存空间的地址, 所以,四个地址没有关联。
#include <stdio.h>
int main()
{
char *a [ ] = {"China","French","America","German"};
printf("%p %p %p %p\n",a[0],a[1],a[2],a[3]); //数组元素中保存的地址
printf("%p %p %p %p\n",&a[0],&a[1],&a[2],&a[3]);//数组元素单元本身的地址
return 0;
}
可以看到 0012FF38 0012FF3C 0012FF40 0012FF44,这四个是元素单元所在的地址,每个地址相差四个字节,这是由于每个元素是一个指针变量占四个字节。。。
char **s;
char **为二级指针, s保存一级指针 char *的地址,关于二级指针就在这里不详细讨论了 ,简单的说一下二级指针的易错点。
举例:
char *a [ ] = {"China","French","America","German"};
char **s = a;
为什么能把 a赋给s,因为数组名a代表数组元素内存单元的首地址,即 a = &a[0] = 0012FF38;
而 0x12FF38即 a[0]中保存的又是 00422FB8 ,这个地址, 00422FB8为字符串"China"的首地址。
即 *s = 00422FB8 = "China";
这样便可以通过s 操作 a 中的数据
printf("%s",*s);
printf("%s",a[0]);
printf("%s",*a);
都是一样的。。。
但还是要注意,不能a = s,前面已经说到,a 是一个常量。。
再看一个易错的点:
char **s = "hello world";
这样是错误的,
因为 s 的类型是 char ** 而 "hello world "的类型是 char *
虽然都是地址, 但是指向的类型不一样,因此,不能这样用。,从其本质来分析,"hello world",代表一个地址,比如0x003001,这个地址中的内容是 'h'
,为 char 型,而 s 也保存一个地址 ,这个地址中的内容(*s) 是char * ,是一个指针类型, 所以两者类型是不一样的。 。。
如果是这样呢?
char **s;
*s = "hello world";
貌似是合理的,编译也没有问题,但是 printf("%s",*s),就会崩溃
why??
咱来慢慢推敲一下。。
printf("%s",*s); 时,首先得有s 保存的地址,再在这个地址中找到 char * 的地址,即*s;
举例:
s = 0x1000;
在0x1000所在的内存单元中保存了"hello world"的地址 0x003001 , *s = 0x003001;
这样printf("%s",*s);
这样会先找到 0x1000,然后找到0x003001;
如果直接 char **s;
*s = "hello world";
s 变量中保存的是一个无效随机不可用的地址, 谁也不知道它指向哪里。。。。,*s 操作会崩溃。。
所以用 char **s 时,要给它分配一个内存地址。
char **s ;
s = (char **) malloc(sizeof(char**));
*s = "hello world";
这样 s 给分配了了一个可用的地址,比如 s = 0x412f;
然后在 0x412f所在的内存中的位置,保存 "hello world"的值。。
再如:
#include <stdio.h>
void buf( char **s)
{
*s = "message";
}
int main()
{
char *s ;
buf(&s);
printf("%s\n",s);
}
二级指针的简单用法。。。。,说白了,二级指针保存的是一级指针的地址,它的类型是指针变量,而一级指针保存的是指向数据所在的内存单元的地址,虽然都是地址,但是类型是不一样的。。。