我想要一些有关字符串和整数的指针的帮助。如果要更改主函数中定义的整数值,则必须传递变量的指针,否则将不会发生任何变化,例如:(a和b将交换为彼此的原始值)
void swapping(int *a,int *b){
int temp=0;
temp= *a;
*a=*b;
*b=temp;
}
int main(){
int a=1,b=2;
swapping(&a,&b);
printf("%d\n%d\n",a,b );
return 0;
}
但是,当我继续传递字符串(char数组)时,这样的操作是可行的:
void split(char take1[],char take2[], char str[]){
int i=0,j=0,yes=0;
while(str[i]!='\0'){
if(str[i]=='*'){
yes=1;
i++;
}
if(yes==0){
take1[i]=str[i];
}
else if (yes!=0){
take2[j]=str[i];
j++;
}
i++;
}
}
int main(){
char taker1[30],taker2[30];
char str[30]="Hello*world";
split(taker1,taker2,str);
printf("%s\n%s\n",taker1,taker2) ;
return 0;
}
我的浅浅理解是因为被调用的函数被临时存储在RAM中,因此一旦函数调用完成,该函数中重新分配的值将被删除。因此,我们需要更改内存中指针的值。
但是我不明白为什么没有必要像第二个示例那样将char数组的指针传递给函数(split()
)来更改其值。有人可以帮忙看看为什么吗?谢谢!
答案 0 :(得分:2)
(OP)但我不明白为什么没有必要像第二个示例那样将char数组的指针传递给function(split())来更改其值。
通过许多操作 1 ,数组将转换为第一个元素的指针。
split(taker1,taker2,str);
让我们深入研究。
C标准库定义了 string
下面的字符串是连续的字符序列,以第一个空字符结尾并包括第一个空字符。 C17dr§7.1.1 1
char
数组str
包含一个字符串。
char str[30]="Hello*world";
char
数组taker1, taker2
未初始化。它们不一定包含 string 。
char taker1[30],taker2[30];
(OP)我继续传递字符串(char数组),
不完全是。下面,char
数组taker1
在传递给函数时被转换为第一个元素的地址。 taker2, str
split(taker1, taker2, str);
split()
接收3个指针,即使它看起来像数组。
void split(char take1[],char take2[], char str[]){
// same as
void split(char *take1, char *take2, char *str) {
split()
的主体然后使用这些指针来操纵数据。回想一下这些指针指向main
的{{1}}。完成str[], taker1[], taker2[]
后,splt()
会显示效果。
1 除非它是
printf("%s\n%s\n", taker1, taker2) ;
运算符的操作数或一元sizeof
运算符的操作数,或者是用于初始化数组的字符串文字,将类型为“ type 的数组”的类型转换为类型为“ pointer to type ”的表达式,该表达式指向数组对象的初始元素,而不是左值。 C17dr
答案 1 :(得分:0)
char take[]
与char *take
基本相同。所以您实际上传递了指针。
例如,在char taker[30]
中,taker
本身就是一个指针,而taker[n]
等效于*(taker + n)
。
答案 2 :(得分:0)
EXPLANATION
这是因为在 C 中,数组声明在内部内部衰减为指针(有关详细信息,请参阅结尾处的引用)。声明char a[]
时,与声明char* a
相同。在这两种情况下,a
都会存储数组第一个元素的内存地址。但是,对于诸如纯整数或字符之类的变量,例如int x = 10;
,变量x
实际上将存储值10
。
当声明一个数组,例如
char a[10];
由表达式a
指定的对象是一个数组(即,足以容纳10个字符值又称为 string 的连续内存块),以及表达式类型{ {1}}是“ 10个字符元素的数组”或a
。表达式char[10]
被隐式转换为a
,其值是第一个元素的地址。
因此,当您将数组变量传递给函数时,实际上是在传递数组的内存地址(或基址)。并且由于您将函数声明编写为:
char *
与写作相同:
void split(char take1[],char take2[], char str[])
而且,在您的函数调用中:
void split(char *take1,char *take2, char *str)
split(taker1,taker2,str);
,taker1
和taker2
实际上包含相应字符数组(即字符串)的基地址。因此,您无需在函数调用中明确提及 address_of运算符(str
)和数组变量。
您发布的代码也可以编写如下:
&
请注意,已互换的数组运算符(void split(char *take1,char *take2, char *str){
int i=0,j=0,yes=0;
while(*(str+i) != '\0'){
if(*(str+i) == '*'){
yes=1;
i++;
}
if(yes==0){
*(take1+i) = *(str+i);
}
else if (yes!=0){
*(take2+i) = *(str+i);
j++;
}
i++;
}
}
int main(){
char taker1[30], taker2[30];
char str[30] = "Hello*world";
split(taker1, taker2, str);
printf("%s\n%s\n", taker1, taker2) ;
return 0;
}
)和取消引用运算符([]
)。 提示:编写*
与arr[5]
相同。
长故事简短:
*(arr + 5)
。奖励
上述原因也是为什么我们不使用&
中的&
作为 string 变量(使用scanf()
格式说明符),即>
%s
但是对于整数或其他基数:
char str[10];
scanf("%s", str);
此外,在C中完成dynamic memory allocation后,您将对所涉及的概念有更好的了解。
引用
以下是C标准(n1256)中的确切语言:
6.3.2.1左值,数组和函数指示符... 3除非它是sizeof运算符的操作数或一元&运算符的运算数,或者是 用于初始化数组的字符串文字,该表达式具有 类型“类型数组”转换为具有类型的表达式 指向数组初始元素的“要输入的指针” 对象,不是左值。如果数组对象具有寄存器存储 类,其行为是不确定的。