字符串和整数的指针

时间:2020-02-13 09:35:52

标签: c pointers

我想要一些有关字符串和整数的指针的帮助。如果要更改主函数中定义的整数值,则必须传递变量的指针,否则将不会发生任何变化,例如:(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())来更改其值。有人可以帮忙看看为什么吗?谢谢!

3 个答案:

答案 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); taker1taker2实际上包含相应字符数组(即字符串)的基地址。因此,您无需在函数调用中明确提及 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]相同。

长故事简短

  • 在C中,数组通过引用传递。普通变量按值传递。
  • 数组变量可以视为指针。
  • 您通常应该在函数调用中跳过使用数组变量的*(arr + 5)

奖励

上述原因也是为什么我们不使用&中的&作为 string 变量(使用scanf()格式说明符),即

%s

但是对于整数或其他基数:

char str[10];
scanf("%s", str);

此外,在C中完成dynamic memory allocation后,您将对所涉及的概念有更好的了解。

引用

以下是C标准(n1256)中的确切语言:

6.3.2.1左值,数组和函数指示符... 3除非它是sizeof运算符的操作数或一元&运算符的运算数,或者是 用于初始化数组的字符串文字,该表达式具有 类型“类型数组”转换为具有类型的表达式 指向数组初始元素的“要输入的指针” 对象,不是左值。如果数组对象具有寄存器存储 类,其行为是不确定的。

相关问题