- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章C语言char s[]和char* s的区别由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
C语言指针可以代替数组使用 。
数组是多个元素的集合,在内存中分布在地址连续的单元中,因此可以通过其下标访问数组的不同数组。 例如: 下面展示一些 。
1
2
3
4
5
|
char
s[3] =
"0x1"
;
printf
(
"s2字符串:\n"
);
printf
(
"%c\n"
, s[0]);
printf
(
"%c\n"
, s[1]);
printf
(
"%c\n"
, s[2]);
|
指针也是一种变量,只不过它的内存单元中保存的是一种标识其他位置的地址,而地址也是整数,在32位平台下,就是32位,4个字节(bytes).
指针的指向 指针的指向是指 指针变量所保存的其他的地址单元中 所存放的数据类型。 例如:
1
2
|
int
*ptr;
//ptr指针保存的地址所在内存单元中的数据类型是整型
float
*p;
//这个p指针指向的内存地址存放的元素类型就是浮点型
|
而不管指向的数据类型是哪种,其实对于指针本身的值永远是整型,因为它保存的地址就是整数 。
字符数组首先是数组,数组中的元素都是字符.
1
|
char
s[10];
//定义了一个含有10个元素的数组,元素类型为字符 %c
|
C语言中定义一个变量时,可以初始化,如下:
1
|
char
s[10] = {
"hello world"
};
|
当编译器遇到上面的定义和赋值时,会将 hello world 和 \0 依次逐个填入连续数组内存中.
C语言中是没有真正的字符串类型,可以通过字符数组表示字符串,并且字符数组的元素地址也是连续的。C语言中规定数组代表数组所在内存位置的首地址,即 str字符串是等于str[0]的,str = &str[0]; 。
对于printf("%s",str); 为什么用首地址就可以输出字符串?
因为对于C语言中字符串常量的本质就是一个地址,例如:
1
2
|
char
*s ;
s =
"Hello"
;
|
这里把一个字符串赋值给一个字符串指针变量,起始就是C语言中编译器会给字符串常量分配地址,如果"Hello", 存储在内存中的 0x3000 0x3001 0x3002 0x3003 0x3004 0x3005 ,可以看出真正的意义就是 s = “Hello” = 0x3000 。
因此我们可以把Hello看做是字符串,而编译器会把他看做是地址 0x3000 ,即字符串常量的本质就是代表它的第一个字符的地址.
1
2
3
|
char
*s;
s =
"Hello"
;
printf
(
"%p\n"
,s);
//%p代表表示按十六进制输出数据,如果输出数据不够8位数,则左边补0
|
输出00796BD0,也就是"Hello"的首地址.
对于字符数组:
char str[10] = “Hello”; 也就是说str = &str[0] 。
C语言中操作字符串是通过它在内存中的存储单元的首地址进行的,这是字符串的终极本质。。.
对于char *s 与 char a[ ] : a代表的是字符串的首地址,而s代表的这个指针保存字符串的首地址(第一个字符的地址),即可以看做: s =a ,即可以将数组名赋值给指针表示地址,但是 不能这样赋值 a = s ,即:不能将指针赋值给数组名 因为数组名是一个常量,是不可以修改的 可以通过如下方式访问数组元素:
1
2
3
4
5
6
7
8
|
char
a[] =
"Hello"
;
char
*s = a;
int
i;
for
(i = 0;i <
strlen
(a);i++)
{
printf
(
"%c"
,s[i]);
//printf("%c",*s++);也可以
}
|
字符指针可以用 间接操作符 * 取其内容,也可以用数组的下标形式 [ ],数组名也可以用 *操作,因为它本身表示一个地址 。.
比如 printf("%c",*a); 将会打印出 ‘H', 。
char * s 与 char a[ ] 的本质区别 。
当定义char a[10]的时候,编译器会给数组分配10个单元,每个单元的数据类型都是字符,而定义char *s时,s是一个指针变量,只占4个字节,32位,用来保存一个地址。 sizeof(a) = 10,sizeof(s) = 4 a的长度是10,s的长度是4,因为s是一个int型 。
printf("%p",s)----------这个表示 s 的单元中所保存的地址.
printf("%p",&s);--------这个表示变量本身所在内存单元地址。。。。,不要搞混了。.
总结:char * s 只是一个保存字符串首地址的指针变量,char a[]是许多连续的内存单元,单元中的元素是char型,char * 和 char a[]具有相同的效果,源于字符串的本质,即给一个字符串地址,便可以操作字符串,但char* 和 char a[]的本质属性不一样.
char *a[] 。
[]的优先级高于 * ,所以先是a[],它是一个数组,数组中的元素是char类型,char元素是一个变量,保存地址。 对于char *a[ ] = {“Dog”,“Cat”,“Chicken”}; 数组中元素是字符串,sizeof(a)是12,并不是4+4+8,是因为字符串常量的本质是地址,a数组中元素是char *指针,指针变量是整数类型,占4个字节,则3个元素就是12个字节.
1
2
|
char
*a[] = {
"Dog"
,
"Cat"
,
"Chicken"
};
printf
(
"%p %p %p \n"
, a[0], a[1], a[2]);
|
可以看到数组中的三个元素保存了三个内存地址,这三个地址代表了三个字符串的首地址,而不是字符串本身,且三个地址不是连续的,它是编译器为"Dog",“Cat”,“Chicken” 分配的内存空间的地址,因此没有关联.
1
2
|
char
*a[] = {
"Dog"
,
"Cat"
,
"Chicken"
};
printf
(
"数组元素单元本身的地址:%p %p %p \n"
, &a[0], &a[1], &a[2]);
//数组元素单元本身的地址
|
可以看到三个元素单元所在的地址是连续的,每个地址相差四个字节.
char ** s 。
char ** 为二级指针,s保存一级指针char *的地址, 例如:
1
2
|
char
*a [ ] = {
"Dog"
,
"Cat"
,
"Chicken"
};
char
**s = a;
//---有问题
|
数组a代表数组元素内存单元的首地址,,即a = &a[0] = 010FFD44,即 *s = 001D6BE0 = “Dog”, 这样可以通过s访问a中的数据 。
1
2
3
|
printf
(“%s”,*s);
printf
(
"%s"
,a[0]);
printf
(
"%s"
,*a);
|
三个一样,,但是不能把a = s,因为a是一个常量; 。
char **s = “hello world”; ------是错误的; 。
因为s的类型是char ** ,而 “hello world”的类型是char *; 。
虽然都是地址, 但是指向的类型不一样,因此,不能这样用。,从其本质来分析,“Hello world”,代表一个地址,比如0x000001,这个地址中的内容是 ‘H',为char型,而s也保存一个地址,这个地址内容是char*,是一个指针类型.
1
2
|
char
**s;
*s =
"hello world"
;
|
编译没有问题,但是 printf("%s",s),就会崩溃, printf ("%s", s); 时,首先得有s 保存的地址,再在这个地址中找到 char * 的地址,即*s,
若s = 0x1000; 在0x1000所在的内存单元保存了“hello world”的地址0x000001,*s = 0x000001,这样printf("%s",*s)会先找到0x1000,然后找到0x000001,如果直接使用char **s,令 * s = “hello world”,s变量中保存的是一个无效随机不可用的值,不知道他指向哪里,所以用char **s时,要给他分配一个内存地址.
1
2
3
|
char
**s ;
s = (
char
**)
malloc
(
sizeof
(
char
**));
*s =
"hello world"
;
|
这样s给分配了一个可用的地址,s = 0x1234,然后再地址0x1234所在的内存中的位置,保存了“hello world”的值.
下列程序中,定义了字符指针s,s中存放了字符串"message"的地址.
1
2
3
4
5
6
7
8
9
10
11
|
#include <stdio.h>
void
buf(
char
**s)
{
*s =
"message"
;
}
int
main()
{
char
*s ;
buf(&s);
printf
(
"%s\n"
,s);
}
|
即:二级指针保存的是一级指针的地址,它的类型就是指针变量,一级指针保存的是指向数据所在的内存单元的地址.
参考: https://blog.csdn.net/daiyutage/article/details/8604720 。
有关于这两者的区别,下面的来自Stack Overflow的解释非常清晰:
http://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s-in-c 。
The difference here is that 。
char *s = "Hello world",
will place Hello world in the read-only parts of the memory and making s a pointer to that, making any writing operation on this memory illegal. While doing
char s[] = "Hello world",
puts the literal string in read-only memory and copies the string to newly allocated memory on the stack. Thus makings[0] = 'J' legal. 。
总结一下,要点如下:
char []
定义的是字符串数组,该字符数组在内存中的存储是先分配新空间,再去填充,因此该数组的内容可以改变,即通过s[0] = 'J'
是合法的。char *s
定义的是字符串指针变量,该指针变量指向一个字符串,该指针的值是该字符串在内存中的地址。对于这个指针变量来说,改变它的值=改变地址=改变指针指向,比如从指向第一个字符变为指向第二个字符。然后改字符指针变量并没有权力去更改它指向的字符的值,比如*(s+1) = 'J'
。换句话说,就是可以修改指针的值,但不能修改指针指向的值。到此这篇关于C语言char s[]和char* s的区别的文章就介绍到这了,更多相关C语言 char s[]和char* s内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.csdn.net/qq_43232556/article/details/118178212 。
最后此篇关于C语言char s[]和char* s的区别的文章就讲到这里了,如果你想了解更多关于C语言char s[]和char* s的区别的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
这个问题在这里已经有了答案: Why don't Java's +=, -=, *=, /= compound assignment operators require casting? (11 个
我搜索了很多,但没有一个链接能帮助我解决这个问题。我得到了 ORA-21500: internal error code, arguments: [%s], [%s], [%s], [%s], [%s
我正在做 RegexOne 正则表达式教程,它有一个 question关于编写正则表达式以删除不必要的空格。 教程中提供的解决方案是 We can just skip all the starting
([\s\S]+|\s?) 中 |\s? 的目的或作用是什么?如果没有它,表达式会不会与 ([\s\S]+) 相同? 最佳答案 这不是完全相同的。 ([\s\S]+|\s?) 会匹配空字符串,而 ([
这个正则表达式有一组还是两组? 我正在尝试使用第二组访问 bookTitle 但出现错误: Pattern pattern = Pattern.compile("^\\s*(.*?)\\s+-\\s+
在 C 中给定一个字符串指针 s,下面的迭代会做什么?即它以什么方式遍历字符串? for (++s ; *s; ++s); 最佳答案 for (++s ; *s;++s) 表示 将指针 s 递增到字符
我正在用一个 node.js 应用程序解析一个大列表并有这段代码 sizeCode = dbfr.CN_DESC.split('\s+-\s*|\s*-\s+') 这似乎不起作用,因为它返回了 [ '
我正在编写一个简单的字符串连接程序。 该程序按照我发布的方式运行。但是,我首先使用以下代码编写它来查找字符串的结尾: while (*s++) ; 但是,这个方法并没有奏效。我传递给它的字符串
这个问题已经有答案了: What does (?和aramchand来自Mohandas Karamchand G 因此,在使用这些匹配来分割字符串后,您最终会得到 {"M", "K", "G"} 注
我正在尝试转换 Map到 List使用 lambda。 本质上,我想将键和值与 '=' 连接起来之间。这看起来微不足道,但我找不到如何去做。 例如 Map map = new HashMap<>();
我正在经历 K & R,并且在递增指针时遇到困难。练习 5.3(第 107 页)要求您使用指针编写一个 strcat 函数。 在伪代码中,该函数执行以下操作: 将 2 个字符串作为输入。 找到字符串
在下面的代码中,pS 和 s.pS 在最后一行是否保证相等?也就是说,在语句S s = S();中,是否可以确定不会构造一个临时的S? #include using namespace std; s
演示示例代码: public void ReverseString(char[] s) { for(int i = 0, j = s.Length-1; i < j; i++, j--){
我一直在寻找类似于 .NET examples 中的示例的 PowerShell 脚本.取一个 New-TimeSpan 并显示为 1 天 2 小时 3 分钟 4 秒。排除其零的地方,在需要的地方添加
def func(s): s = s + " is corrected" return s string_list = ["She", "He"] for s in string_li
我是 python 的新手。当我在互联网上搜索 lambda 时。我在 lambda_functions 中找到了这个声明. processFunc = collapse and (lambda s:
我最近开始学习正则表达式,并试图为上面的问题写一个正则表达式。如果限制只放在一个字母上(例如不超过 2 个“b”),这并不困难。 那么答案就是:a* c*(b|ε)a* c*(b|ε)a* c* 但是
当我运行 npm install 时出现以下错误,但我无法修复它。 我试过:npm install -g windows-build-tools 也没有修复这个错误 ERR! configure
有很多有趣的haskell网上可以找到片段。 This post可以在 this (awesome) Stack Overflow question 下找到. The author写道: discou
我知道以下三行代码旨在将字符串提取到$ value中并将其存储在$ header中。但是我不知道$value =~ s/^\s+//;和$value =~ s/\s+$//;之间有什么区别。 $val
我是一名优秀的程序员,十分优秀!