字符串?字符数组?指针?傻傻分不清楚

    首先我们来看一下下面这个程序,不妨先猜猜它会输出什么哟。

#include<stdio.h>
#include<string.h>
int main(void)
{
    int a[5] = {1,2,3,4,5};
    int i = 1;
    char str1[] = "HelloWorld\n";//数组除了在被运算符sizeof操作的时候不是直接看作地址外,其余都是可以直接等同于这个数组首元素的地址的。即一个指向首元素的指针
    char *str2 = "HelloWorld\n";
    char *str6 = {"HelloWorld\n"};
    char str3[] = {"HelloWorld\n"};//事实上等同于第一种
    char str4[] = {‘H‘,‘e‘,‘l‘,‘l‘,‘o‘,‘W‘,‘o‘,‘r‘,‘l‘,‘d‘,‘\n‘,‘\0‘};
    char str5[] = {‘H‘,‘e‘,‘l‘,‘l‘,‘o‘,‘W‘,‘o‘,‘r‘,‘l‘,‘d‘,‘\n‘};//末尾没有加 \0 结束符  最后可能会输出该数组外内存里的东西
    printf("%d  %d   %d\n",a[i],i[a],3[a]);//当执行a[i]时   事实上等同于*(a+i);   而a + i  ==  i + a;  所以,我们用i[a]也可以达到目的  同样的  3[a]也是
    //str1[2] = ‘M‘;    // 位置1
    printf(str1);
    //str1[2] = ‘M‘;    // 位置2
    //str2 = "This a Test";    // 位置3
    printf(str2);
    printf(str3);
    printf(str4);
    printf(str5);
    printf("strlrnResult:  %d %d %d %d %d\n",strlen(str1),strlen(str2),strlen(str3),strlen(str4),strlen(str5));
    printf("sizeofResult:  %d %d %d %d %d\n",sizeof(str1)/sizeof(str1[0]),sizeof(str2)/sizeof(str2[0]),sizeof(str3)/sizeof(str3[0]),sizeof(str4)/sizeof(str4[0]),sizeof(str5)/sizeof(str5[0]));
}

    前面各个字符串的输出结果相信大家应该都很清楚,第五个的结果在不同机器上运行的到的结果可能会不同,事实上也存在一定的偶然性,这里我们不讨论它们,我们主要一起讨论一下定义以及最后两行输出的结果分析。

  我们在C语言里,想要定义一个所谓的字符串,事实上是通过定义一个字符数组来实现的:像系统申请一块内存,然后可以再定义的时候一次性给它们都放入元素,也可以事后另外再一个个给它们赋值,要注意,如果不在定义的时候一次性赋值,后面就不要尝试偷懒直接把用双引号包住的东西直接给它了哟。

  通常我们想使用字符串时定义使用比较多的方式主要是这两种:1、通过定义一个字符数组,并在初始的时候直接把一个字符串常量的值给它或者是通过一个个字符的形式赋值,如果是后者,一定不要忘记‘\0‘符号。在定义一维字符数组的时候,如果直接给它赋初值了,那么数组的长度可以不显示给出  2、定义一个字符指针,并让它指向字符串常量。(注意,是常量哟,如果非刻意如此,不建议这么做)或者是让它指向另一个数组。(这也是指针的灵活性所在)

  当我们使用字符指针来操作时,大家可千万别让它直接指向了一个常量!为什么?因为如果你非刻意需要一个常量的话,那你这么做的确是有点多余了。

  这个指针指向的这个常量你不知道它在哪,你也不知道怎么修改值。当你需要做出改变的时候,你会发现无从下手,最后你只能无奈的放弃让这个指针指向它从而重新弄一块内存重新的到一片可控的空间。不妨试试把位置1、位置2和位置3分别取消注释看看结果,并想想为什么。

  你可能要说,我本来就需要这么一个常量,我就喜欢这么做。那为什么不考虑考虑宏定义,就一定要吊死在字符指针这一棵树上呢?或许那是个更好的选择。

  关于定义我们就讨论这么多啦,接下来看看最后的两个输出结果吧。

 

strlrnResult:  11 11 11 11 23
sizeofResult:  12 4 12 12 11

  我们用函数strlen与运算符sizeof分别求得的结果为什么会不一样呢?我们简单分析一下就知道了:

  str1和str3两种方式输出的结果不一样 是因为我们在定义字符数组的时候,如果非第四、五种定义方式,会自动为你补上一个NUL结束符作为字符的结束符。函数strlen是以‘\0‘(即NUL,注:并不存在这样的保留字)为结束条件的,所以strlen未计算结束符‘\0‘。而运算符sizeof(str)是计算这个数组总共花费的内存大小/数组每个元素大小,也就是它包括了结束符在里面。 故后者得到的结果比前者大1.
  str2两种方式输出的结果不一样 是因为str2是采用了字符指针的方式定义的,指针的长度在同一台电脑上所占的长度是一致的。(在32位电脑中应该是4)。因为不管是什么指针,它事实上就是一个地址,使用4个字节可以存下。故sizeof(str2)得到的是这个指针本身所占的内存的大小。而strlen是将这个指针作为字符数组来对待的,因此计算的是字符数组真正的长度。
  str5两种方式输出的结果不一样,是因为前者未在自己本来地盘(也就是自己申请的那块内存)的末尾加上‘\0‘,因此使用strlen会一直往后找,判断后面的是不是‘\0‘,直到找到或者产生错误。(注:极可能发生严重的错误,尽管我自己电脑并没有,它找到了str4的结束符停止了并把str5与str4、str4的整体都包含进来了)。  而sizeof计算时,当时系统是为其分配了11个sizeof(str5[0])长度 所以结果自然就为11咯。

原文地址:https://www.cnblogs.com/YaLi/p/9786082.html

时间: 2024-07-31 08:07:18

字符串?字符数组?指针?傻傻分不清楚的相关文章

复习一下整型数组,字符数组,整型指针数组,字符指针数组,整型数组指针,字符数组指针

20:52:01 2019-12-31 整型数组 int a[10];字符数组 char b[10]; _______________________整型指针数组 int *p[10]; |__|__|__|__|__|__|__|__|__| 每个格子里存的是一个指针,每个指针都是int类型的,会指向一个int的值. 1 for(int i=0; i<10; i++) 2 p[i] = &a[i]; //把a中的每个元素的地址都放在了指针数组p里. 3 4 for(int j=0; j&l

字符 字符串 字符数组 字符串指针 指针数组

一.字符串指针.字符数组 1. 字符串指针:字符串指针变量本身是一个变量,用于存放字符串的首地址.而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以'\0'作为串的结束. char *ps="C Language"; 可以写为: char *ps;  #ps字符串指针,是指针,是一个变量, ps="C Language"; #ps为字符串的首地址,利用ps++可遍历字符串,字符串存储在以ps为开始地址的地段连续的内存空间中,并以'\0'作为字符串的结束.

字符串字符数组

1 #define _CRT_SECURE_NO_WARNINGS 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 int main() 6 { 7 8 /* 9 字符串的赋值: 10 给 char* 类型的字符串赋值,可以直接使用 "=" 号 11 给 char[] 类型的字符串赋值,需要使用 strcpy 函数 12 13 字符串的特点: 14 需要明白的一点就是字符串以\0结尾, 没有\0就不是字符串 15 只

指针 指针与数组 指针与字符串 指针与函数 结构体与指针 宏

指针 指针与数组 指针与字符串 指针与函数?? 指针与数组 1.数组名:数组元素首地址 eg: int array[3]={1,3,6}; 这里array 恒等于&array[0] 2.int *p = a; int *p = 0; int a[]={0}; 3.int *p = a; 均指向数组的首地址 *p是? *(p+1)是?(*p)+1是? *(p+1)决定向下移动几个字节是类型 4.指针可以当数组名使用 p[1] = 3; 恒等于a[1] ;恒等于*(p+1);恒等于*(a+1) 5.

c语言字符数组与字符串的使用详解

转自:http://www.jb51.net/article/37456.htm 1.字符数组的定义与初始化字符数组的初始化,最容易理解的方式就是逐个字符赋给数组中各元素.char str[10]={ 'I',' ','a','m',' ',‘h','a','p','p','y'};即把10个字符分别赋给str[0]到str[9]10个元素如果花括号中提供的字符个数大于数组长度,则按语法错误处理:若小于数组长度,则只将这些字符数组中前面那些元素,其余的元素自动定为空字符(即 '\0' ). 2.

字符、字符串、数组

1.字符数组的定义与初始化 字符数组的初始化,最容易理解的方式就是逐个字符赋给数组中各元素. char str[10]={ 'I',' ','a','m',' ','h','a','p','p','y'}; 即把10个字符分别赋给str[0]到str[9]10个元素 如果花括号中提供的字符个数大于数组长度,则按语法错误处理:若小于数组长度,则只将这些字符数组中前面那些元素,其余的元素自动定为空字符(即 '\0' ). 2.字符数组与字符串 在c语言中,将字符串作为字符数组来处理.(c++中不是)

Delphi字符串、PChar与字符数组之间的转换

来自:http://my.oschina.net/kavensu/blog/193719 ----------------------------------------------------------------- var s: string; p: pchar; a: array[1..20] of char; 1.字符串 ---> PChar p := PChar(s); 2.PChar ---> 字符串 s := p; 3.PChar ---> 字符数组 StrCopy(@a

c语言字符数组的初始化问题

1.字符数组的定义与初始化 字符数组的初始化,最容易理解的方式就是逐个字符赋给数组中各元素. char str[10]={ 'I',' ','a','m',' ',‘h’,'a','p','p','y'}; 即把10个字符分别赋给str[0]到str[9]10个元素 如果花括号中提供的字符个数大于数组长度,则按语法错误处理: 若小于数组 长度,则只将这些字符数组中前面那些元素,其余的元素自动定为空字符(即 '\0' ). 2.字符数组与字符串 在c 语言中,将字符串作为字符数组来处理.(c++中

C语言字符数组的定义与初始化

C 语言字符数组的定义与初始化 1.字符数组的定义与初始化字符数组的初始化,最容易理解的方式就是逐个字符赋给数组中各元素.char str[10]={ 'I',' ','a','m',' ',‘h’,'a','p','p','y'};即把10个字符分别赋给str[0]到str[9]10个元素如果花括号中提供的字符个数大于数组长度,则按语法错误处理:若小于数组长度,则只将这些字符数组中前面那些元素,其余的元素自动定为空字符(即'\0' ).2.字符数组与字符串在c 语言中,将字符串作为字符数组来处

C零基础视频-37-指针数组与数组指针

目录 指针数组 数组指针 指针数组 指针数组是数组,即一个数组中,每个元素都是指针. #include <stdio.h> int main(int argc, char* argv[]) { int nValue1 = 1; int nValue2 = 2; int nValue3 = 3; int * nArray[3] = { &nValue1, &nValue2, &nValue3 }; char* sz1 = "hello"; char*