문자 배열 및 문자 포인터
问题1:
字符数组名可以作为左值吗?当然不行
比如
char str[20] = {'h','e','l','l','o',' ','w','o','r','l','d'};
str++;
不可以这么干,因为字符数组名是一个常量指针,也就是是一个const char*
#include <stdio.h> int main() { char str[20] = {'h','e','l','l','o',' ','w','o','r','l','d'}; printf("sizeof(str): %d\n",sizeof(str)); printf("str: %s\n",str); str = str + 1; //error return 0; }
运行结果如下:
当数组名为左值时,它的类型是字符数组;当数组名为右值时,它的数据类型是字符指针。
#include <stdio.h> #include <string.h> int main(void) { char buf[10]; char *p= “afdal”; buf = p; //将一个char* 赋给一个char[10],类型不一样,必然不成功 printf(“the buf is:%s\n”,buf); return 0; }
问题2:
字符数组如何进行初始化?
#include <stdio.h> int main() { char ptr[20] = "hello world"; //success char str[20] = {'h','e','l','l','o',' ','w','o','r','l','d'}; //success char ctr[20]; ctr = "hello world"; // error: incompatible types when assigning to type ‘char[20]’ from type ‘char *’ return 0; }
在给字符数组初始化的时候,会自动在字符数组的结尾加上'\0'
#include <stdio.h> int main() { char str[20] = {'h','e','l','l','o',' ','w','o','r','l','d'}; printf("sizeof(str): %d\n",sizeof(str)); printf("str: %s\n",str); int i = 0; while(*(str + i) != '\0') //判断是否加上'\0' { printf("%c\n",*( str + i++)); } return 0; }
运行结果如下:
问题3:
字符数组越界访问能编译通过吗?
字符数组越界访问编译可以通过,没有报错,这样会出现很多的问题
#include <stdio.h> int main() { char str[12] = {'h','e','l','l','o',' ','w','o','r','l','d'}; printf("%c\n",str[100]); return 0; }
打印为空
问题4:
字符数组和字符指针又有什么区别呢?
首先在内存的中位置不同,字符数组保存的字符串存放在内存的栈中,而字符指针指向的字符串保存在内存的静态存储区中。
其次字符数组保存的字符串属于字符串变量,可以被修改,而字符指针指向的字符串是属于字符串常量,不能被修改。
#include <stdio.h> int main() { char str[12] = {'h','e','l','l','o',' ','w','o','r','l','d'}; char* ptr = "hello world"; str[0] = 'f'; ptr[0] = 'f'; //将字符指针指向的字符串修改,将出现段错误,因为该内存地址只读,因为该字符串属于常量 return 0; }
运行结果:
段错误是指访问的内存超出了系统给这个程序所设定的内存空间,例如访问了不存在的内存地址、访问了系统保护的内存地址、访问了只读的内存地址等等情况。
#include <stdio.h> int main() { char* ptr = "hello world"; ptr[11] = '!'; //往常量字符串末尾添加字符,相当于连接两个字符串,出错 ptr[12] = '\0'; return 0; }
这样也会出现段错误。
问题5:
字符指针是不是和字符数组名都是指针常量呢?
不是,字符指针,可以改变它的指向,也就是可以为左值。可以将一个字符指针指向一个字符串常量后又指向另外一个字符串常量。字符指针在为初始化之前,他是一个未定义的值,将指向任何可能的地方,所以在使用字符指针时一定要注意初始化。
#include <stdio.h> int main() { char* ptr; printf("ptr: %c\n",*ptr); return 0; }
运行结果:
编译可以通过,但是ptr指向的内存地址是任意的
当然也可以将一个字符指针指向一个字符数组。
#include <stdio.h> int main() { char str[12] = {'h','e','l','l','o',' ','w','o','r','l','d'}; char* ptr = str; printf("ptr: %s\n",ptr); return 0; }
运行结果:
问题6:
如果一个字符指针指向一个堆中动态内存。那么我们如何初始化该内存中的值?
#include <stdio.h> #include <stdlib.h> int main() { char* str = (char*)malloc(sizeof(char)*20); printf("str:%p\n",str); //str在堆中内存首地址 str = "hello world"; printf("str:%p\n",str); //str在静态存储区内存首地址 char* ptr = "I love you"; printf("ptr:%p\n",ptr); //str在静态存储区内存首地址 return 0; }
运行结果如下:
很明显前后的地址不一样,前一个指向堆中的内存的地址,而后一个指向了静态存储区中的内存的地址。我本以为我通过上述方式进行初始化str的时候,我可以将堆中内存进行初始化,我发现我错了,字符指针将被重新指向。但是我想如果我们将str声明为const呢?那将会出现什么样的结果呢?
#include <stdio.h> #include <stdlib.h> int main() { const char* str = (char*)malloc(sizeof(char)*20); //我以为const将修饰str,使得str不能再作为左值而出现,我错了,const修饰的是由str指向的字符串, printf("str:%p\n",str); //该字符串不能再被修改 str = "hello world"; printf("str:%p\n",str); return 0; }
运行结果:
如果我们将上述的代码做如下修改,程序还能编译通过吗?
#include <stdio.h> #include <stdlib.h> int main() { const char* str = (char*)malloc(sizeof(char)*20); printf("str:%p\n",str); str[0] = 'h'; //这种赋值才是对str原来所指向的堆中的内存的赋值,编译不过,因为str指向的堆中的内存是只读的。 str = "hello world"; printf("str:%p\n",str); return 0; }
运行结果如下:
上述就引发了我思考为什么const修饰的是str指向的字符串,而不是str本身呢?
原来,char* const str才是真正的修饰str本身,使得str为只读的,不能再被修改,也就是重新指向其他内存地址。而const char* str 和 char const* str 的意义是一致的,都是修饰的是*str。
#include <stdio.h> #include <stdlib.h> int main() { char* const str = (char*)malloc(sizeof(char)*20); printf("str:%p\n",str); str[0] = 'h'; str = "hello world"; //变量str被重新指向,error,编译不过 printf("str:%p\n",str); return 0; }
运行结果如下:
那么我们又该如何初始化一个字符指针指向的内存呢?
其实我们可以很清楚的分析,如果str是一个字符指针,也就是一个变量,变量是可以被重新赋值的,而每一个字符串本身是有一个地址的,str = “hello world”,必然就是改变了str的值,使得str保存着"hello world"的内存首地址,而一旦你将str = "I love you",必然str将保存这"I love you"的内存首地址,这都是毋庸置疑的。
#include <stdio.h> int main() { printf("hello world:%p\n","hello world"); //将打印出"hello world"的内存地址 printf("I love you:%p\n","I love you"); //将打印出"I love you"的内存地址 return 0; }
运行如下:
下面我得回到这样一个问题?
str 和 *str的区别,很明显,str是一个指针,而*str是str指向的内存的存放的值,既然我们想改变str指向内存中的值,既*str的值,那么为何不将*str作为左值,来初始化str所指向内存的值呢?而*str 不就是 str[0]吗?所以很明显了。上述问题:那么我们又该如何初始化一个字符指针指向的内存呢?当然这个仅限于字符指针指向的是由mlloc分配的堆中的内存以及字符数组指向的栈中的内存。而字符指针如果指向字符常量,不可修改字符指针指向的内存的值,因为字符常量是只读的。
#include <stdio.h> #include <stdlib.h> int main() { char* const str = (char*)malloc(sizeof(char)*20); printf("str:%p\n",str); str[0] = 'A'; //数组下标型赋值 *(str + 1) = 'l'; //指针++型赋值 str[2] = 'e', *(str + 3) = 'x'; printf("str:%s\n",str); printf("str:%p\n",str); return 0; }
运行如下:
#include <stdio.h> #include <stdlib.h> int main() { char str[20]; printf("str:%p\n",str); str[0] = 'A'; *(str + 1) = 'l'; str[2] = 'e', *(str + 3) = 'x'; //str[4] = '\0'; //当我们没有手动给字符串结尾附上'\0' printf("str:%s\n",str); printf("str:%p\n",str); return 0; }
运行如下:
上述的运行结果说明上述程序并没有自动给字符串结尾附上'\0',对于字符数组除非这样赋值,str[20] = "hello world",不然你就得手动给字符串附上字符串结尾'\0'。
#include <stdio.h> #include <stdlib.h> int main() { char str[20]; printf("str:%p\n",str); str[0] = 'A'; *(str + 1) = 'l'; str[2] = 'e', *(str + 3) = 'x'; str[4] = '\0'; printf("str:%s\n",str); printf("str:%p\n",str); return 0; } ~
运行结果:
附上一段我关于memcpy()和memmove()的代码的实现。
#include <stdio.h> #include <stdlib.h> void mem_copy(char* const dest, const char* const src) { for(int i = 0; *(src + i) != '\0'; i++) *(dest + i) = *(src + i); } void mem_move(char* const dest, const char* const src) { int i = 0; while(*(src + i) != '\0') i++; for(; i != -1; i--) *(dest + i) = *(src + i); } int main() { char* src = "hello world"; char* const dest1 = (char*)malloc(sizeof(char) * 20); char dest2[20]; mem_copy(dest1,src); mem_move(dest2,src); printf("dest1:%s\n",dest1); printf("dest2:%s\n",dest2); return 0; }
当我们需要将内存的中的某一地址段的内容拷贝到内存中另一地址段中,以上是将字符串常量区的内容拷贝到堆中和栈中,我们可以看到我分别使用了malloc和字符数组,当然我们得考虑可能在拷贝的过程中会有地址段重叠的问题,重叠该怎么拷贝,解决方案很简单,就是从尾向前拷贝,即可。
运行结果如下:
以上是我对c语言中字符串操作的一些理解

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











SPLIT() 함수는 문자열을 지정된 구분 기호로 배열로 분할하여 각 요소가 원래 문자열의 구분 기호로 구분된 부분인 문자열 배열을 반환합니다. 사용법에는 쉼표로 구분된 값 목록을 배열로 분할하고, 경로에서 파일 이름을 추출하고, 이메일 주소를 사용자 이름과 도메인으로 분할하는 것이 포함됩니다.

Java에서 문자열을 정렬하는 방법: Arrays.sort() 메서드를 사용하여 문자열 배열을 오름차순으로 정렬합니다. 문자열 목록을 오름차순으로 정렬하려면 Collections.sort() 메서드를 사용합니다. 문자열의 사용자 정의 정렬을 위해 Comparator 인터페이스를 사용하십시오.

C 언어에서 \0은 널 문자 또는 종결자라고 하는 문자열의 끝 표시입니다. 문자열은 바이트 배열로 메모리에 저장되므로 컴파일러는 \0을 통해 문자열의 끝을 인식하여 문자열이 올바르게 처리되도록 합니다. \0 작동 방식: 컴파일러는 \0을 발견하면 문자 읽기를 중지하고 후속 문자는 무시됩니다. \0 자체는 저장 공간을 차지하지 않습니다. 이점에는 안정적인 문자열 처리, 향상된 효율성(끝을 찾기 위해 전체 배열을 스캔할 필요 없음), 손쉬운 비교 및 조작이 포함됩니다.

args는 Java의 명령줄 인수를 나타내며 프로그램이 시작될 때 프로그램에 전달되는 인수 목록을 포함하는 문자열 배열입니다. 이는 기본 메소드에서만 사용할 수 있으며 기본값은 인덱스로 액세스할 수 있는 각 매개변수가 있는 빈 배열입니다. args는 프로그램이 시작될 때 입력 데이터를 구성하거나 제공하기 위해 명령줄 인수를 수신하고 처리하는 데 사용됩니다.

args는 명령줄 매개변수 또는 외부 입력의 문자열 배열을 얻는 데 사용되는 Java 기본 메소드의 특수 매개변수 배열입니다. args 배열에 액세스함으로써 프로그램은 이러한 인수를 읽고 필요에 따라 처리할 수 있습니다.

AI 기술과 PHP 기능을 결합해 애플리케이션의 기능을 강화했습니다. 특정 AI 애플리케이션에는 다음이 포함됩니다. Naive Bayes와 같은 기계 학습 알고리즘을 사용하여 텍스트를 분류합니다. 단어 분할 및 형태소 분석과 같은 자연어 처리 기술을 사용하여 심층적인 텍스트 분석을 수행합니다.

C 언어 프로그래밍 소프트웨어에서 한자 정렬 기능을 구현하는 방법은 무엇입니까? 현대사회에서 한자 정렬 기능은 많은 소프트웨어에서 필수적인 기능 중 하나이다. 워드 프로세싱 소프트웨어, 검색 엔진 또는 데이터베이스 시스템에서 중국어 텍스트 데이터를 더 잘 표시하고 처리하려면 중국어 문자를 정렬해야 합니다. C언어 프로그래밍에서 한자 정렬 기능을 어떻게 구현하나요? 그 중 하나의 방법을 아래에 간략하게 소개합니다. 먼저 C언어에서 한자 정렬 기능을 구현하기 위해서는 문자열 비교 기능을 사용해야 한다. 란

C++ 프로그램 성능에 대한 함수의 영향에는 함수 호출 오버헤드, 로컬 변수 및 객체 할당 오버헤드가 포함됩니다. 함수 호출 오버헤드: 스택 프레임 할당, 매개변수 전송 및 제어 전송을 포함하며 이는 작은 함수에 상당한 영향을 미칩니다. 지역 변수 및 개체 할당 오버헤드: 지역 변수 또는 개체 생성 및 소멸이 많으면 스택 오버플로 및 성능 저하가 발생할 수 있습니다.
