********* 二维数组指针,指针字符串,指针函数,函数指针 *********

本文详细介绍了C语言中指针的应用,包括二维数组指针的定义与使用、字符串指针的概念与操作、指针函数及函数指针的实现方式。通过实例展示了如何利用这些特性进行高效编程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



//  二维数组指针定义.初始化

//

//  Created by 李佳乐 on 15-3-17.

//  Copyright (c) 2015 gongsimingzi. All rights reserved.

//


#include <stdio.h>


int main(int argc, const char * argv[]) {

    //定义一个二维数组

    int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

    

    //定义一个二维数组指针

    int (*p)[4]=a;

    

    //使用二维数组指针遍历

    for(int i = 0;i<3;i++){

        for(int j = 0;j<4;j++){

            printf("%d\t",*(*(a+i)+j));

        }

        printf("\n");

    }

    printf("Hello, World!\n");

    return 0;

}




//  用数组名访问二维数组

//

//  Created by 李佳乐 on 15-3-17.

//  Copyright (c) 2015 gongsimingzi. All rights reserved.

//

// ******************* a[i]+j 代表的是a[i][j]的坐标


// ******************* *(a[i]+j) 代表的是a[i][j]的值


#include <stdio.h>


int main(int argc, const char * argv[]) {

    // 定义一个二维数组

    int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

    printf("a=%p,a[0]=%p,&a[0][0]=%p\n",a,a[0],&a[0][0]);//地址相同

    

    

    //*(*(a+i)+j)   代表a[i][j]的值

    printf("a[0]+1=%p ==  &a[0][1] = %p ----> %d\n",a[0]+1,&a[0][1],a[0][1]);

    printf("a[0]+2=%p ==  &a[0][2] = %p ----> %d\n",a[0]+2,&a[0][2],*(a[0]+2));

    printf("a[0]+3=%p ==  &a[0][3] = %p ----> %d\n",a[0]+3,&a[0][3],*(a[0]+3));

    

    for(int i = 0;i < 3;i++){

        for(int j = 0;j < 4;j++){

            printf("a[%d][%d] = %d \n",i,j,*(*(a+i)+j));

        }

    }

    

    printf("Hello, World!\n");

    return 0;

}



//  字符串指针

//

//  Created by 李佳乐 on 15-3-19.

//  Copyright (c) 2015 gongsimingzi. All rights reserved.

//



/*

 字符串指针

 

 定义: char *字符串指针变量名="字符串"内容;

 

 用来保存一个字符串

 

 常量区 就是存储一个已经被缓存的常量 

 经常使用  常量区不可以对常量进行修改

 在常量区保存的数据都只读的

 */


/*

#include <stdio.h>


int main(int argc, const char * argv[]) {

    // "asdgfsadfgsdfg" 这个字符串存储在常量区

    //str 只保存了字符串常量的首地址

    char *str="asd";

    

    //指针变量都是占用8个字节

    printf("%ld\n",sizeof(str));

    printf("%s\n",str);

    //str是指针变量

    //str重新指向另外一个字符串常量 "i love you"

    //保存的是"i love you"字符串常量的首地址

    

    str = "i love you";

    printf("%s\n",str);

    

    char ch[]="abc"; //字符串数组存在栈区,可以进行修改

    ch[2]='z';

    printf("%s\n",ch);

    

    //读取字符串常量的某个字符

    for(int i =0;i<10;i++){

        printf("%c\t",*(str+i));

    }

 

    return 0;

}

*/


//字符串指针  指向的时一个字符串的首地址


#include <stdio.h>


int main(){

    

    //定义一个字符串指针

    char *str="abc";

    //str是变量,所以可以改变指向,而字符串是常量,所以不可以重新修改

    

    str = "hello";

    

//    //变量字符串的元素

//    for(int i = 0;i < 5;i++){

//        printf("%c\n",*(str+i));

//    }

    printf("%s\n",str);

    

    return 0;

}




//  指针函数

//

//  Created by 李佳乐 on 15-3-19.

//  Copyright (c) 2015 gongsimingzi. All rights reserved.

//


//指针函数返回值为一个地址(它是一个函数,返回值为地址)


//#include <stdio.h>

//定义一个函数,传递两个整数,返回大数的地址

/*

int * max(int *pa,int *pb){

    

    return *pa > *pb ? pa : pb;

    

}


int main(int argc, const char * argv[]) {

    // 定义两个变量

    int a = 10,b = 5;

    

    printf("a = %p\nb = %p\n",&a,&b);

    int *p = max(&a,&b);

    

    printf("%p\n",p);

    return 0;

}

*/

#include <stdio.h>

//定义一个指针函数


int * max(int *pa,int *pb){

    return *pa>*pb? pa : pb;

}


int main(){

    //定义两个变量

    int a=10,b=5;

    printf("a = %p\nb = %p\n",&a,&b);

    

    //定义指针的同时初始化

    int *p = max(&a, &b);

    

    printf("p = %p\n",p);

    

    return 0;

}




//  函数指针

//

//  Created by 李佳乐 on 15-3-19.

//  Copyright (c) 2015 gongsimingzi. All rights reserved.

//

/*

 函数指针的定义格式

 被指向的函数的返回值类型 (*函数指针变量名)(被指的函数的参数)

 

 

 

 */


/*

#include <stdio.h>


int max(int x,int y){

    

    return x > y? x : y;

    

}


int sum(int x,int y){

    

    return x+y;

}


int main(int argc, const char * argv[]) {

    // 定义了一个函数指针,指针变量名是pmax,它只能指向返回值是int 并且有两个int类型参数的函数

  //  int (*pmax)(int x,int y);

    //得到了指向函数的返回值

    int (*p)(int x,int y);

    int a = 5;

    

    if(a >5){

        p = max;

    }else{

        p = sum;

    }

    //函数指针的使用

    

    int m = (*p)(438,78);//int m = p(438,78);

    

    printf("%d\n",m);

    return 0;

}

*/


//函数指针  定义一个函数指针 指向的是函数的首地址,得到函数的返回值


#include <stdio.h>

//定义一个函数

int sum(int x,int y){

    return x+y;

}


int cheng(int x,int y){

    return x * y;

}

int main(){

    

    //定义一个函数指针

    int (*p)(int x,int y);

    //给函数指针初始化

    p = sum;

    //调用

    int m = (*p)(10,5);

    

    printf("%d\n",m);

    

    return 0;

}


<think>我们正在处理C++11中char*数组使用字符串初始化的问题。根据用户的问题,他想知道在C++11中如何用字符串初始化char*数组。注意:在C++11中,字符串字面量是常量,类型为`const char[N]`,因此不能直接赋值给`char*`(因为这会丢弃const限定符)。但是,我们可以通过一些方法来实现。方法1:使用字符数组初始化(每个字符串字面量初始化一个字符数组,然后数组内容可修改)方法2:如果不需要修改字符串,可以将数组声明为`constchar*`类型。方法3:使用显式类型转换(不推荐,因为修改常量字符串会导致未定义行为)。根据引用[1]中的警告,ISO C++禁止将字符串常量转换为'char*',因此直接赋值给`char*`是不安全的,并且会引发警告。我们来看引用[2]中提到的字符数组初始化:`char str[] ="string";`这种方式是合法的,因为这里str是一个数组,它被字符串字面量初始化,并且可以修改(因为数组存储的是副本,而不是指向字面量的指针)。但是,如果我们要初始化一个`char*`数组(即指针数组),每个指针指向一个字符串,那么我们需要考虑字符串常量性。因此,对于`char*`数组的初始化,我们可以这样:-如果字符串不需要修改,则使用`constchar*`数组。-如果字符串需要修改,那么每个指针应该指向一个可修改的内存(比如使用字符数组或者动态分配内存并复制字符串)。下面我们给出几种初始化`char*`数组(指针数组)的方法:示例1:使用`constchar*`(字符串不可修改) ```cppconst char* arr[] ={"Hello", "World"};```示例2:使用二维字符数组(每个字符串可修改,但长度固定)```cppchararr[][10] ={"Hello", "World"}; //每个字符串最大长度为9(预留一个字符给结束符)```示例3:使用指针数组,但每个指针指向一个可修改的字符串副本(需要动态分配内存,并记得释放)这种方法比较复杂,一般不推荐,除非字符串长度变化很大。示例4:如果非要用`char*`(而不是`const char*`)且不想用二维数组,那么我们可以将字符串字面量赋值给`char*`,但这是不安全的,并且会触发警告。在C++11中,我们可以使用显式类型转换去掉常量性,但这样做有风险(因为试图修改常量字符串会导致未定义行为): ```cppchar*arr[]= {const_cast<char*>("Hello"), const_cast<char*>("World")}; //注意:这样做的后果是,如果你试图修改这些字符串,程序可能会崩溃。```因此,推荐的方法是:-如果不需要修改字符串,使用`const char*`数组。-如果需要修改,使用二维字符数组(固定长度)或者使用`std::string`(推荐)。但是用户明确要求使用`char*`数组,并且使用字符串初始化。所以,我们假设用户需要的是指针数组,每个指针指向一个字符串。在C++11中,我们可以这样安全地初始化一个`char*`数组(可修改):-首先,我们需要为每个字符串分配可修改的内存,然后复制字符串内容。但是这样初始化比较麻烦,我们可以写一个辅助函数或者使用循环。不过,在初始化时直接完成可能比较困难。另一种方法是使用一个字符数组的数组(即二维字符数组)作为存储,然后将指针数组的元素指向这些二维数组的每一行。这样,每个字符串都是可修改的,且存储在栈上(如果是局部变量)。例如: ```cppchar s1[]= "Hello";char s2[]= "World";char*arr[]= {s1, s2};```但是这样写比较冗长。我们可以使用复合字面量(C99特性)?但C++不支持复合字面量。在C++11中,我们可以使用初始化列表和lambda表达式来创建一个临时的字符数组,但是这样并不直接。实际上,更简洁的方式是使用二维字符数组,然后将其行首地址赋给指针数组:```cppcharstrings[][10] ={"Hello", "World"}; //二维数组,每个字符串长度不超过9char*arr[]= {strings[0],strings[1]};```或者,我们可以直接写:```cppchar*arr[]= {(char[])"Hello", (char[])"World" };```注意:`(char[])"Hello"`是一个C风格的转换,它创建了一个字符数组(类型为char[6]),并用字符串字面量初始化,然后这个数组会退化为指针。但是,这种写法在C++中也是合法的,并且数组的内容是可修改的(因为它是字符串字面量的一个副本吗?实际上,标准允许编译器将字符串字面量存储在只读区域,但是这种写法创建了一个可修改的数组,并用字符串字面量初始化,所以是安全的可修改副本)。然而,这种写法在C++11中是否允许?实际上,这是GNU扩展,标准C++不支持这种复合字面量(C99支持,但C++没有)。因此,在C++中,我们应该避免这种写法。所以,最安全且标准的方法是:-使用二维字符数组存储字符串(可修改),然后用指针数组指向它们。但是,如果数组元素很多,写起来会很麻烦。我们可以使用循环来初始化指针数组。总结:在C++11中,初始化一个可修改的`char*`数组(指针数组)的最直接方法是:-先定义二维字符数组(存储字符串,可修改)-再定义指针数组,每个元素指向二维数组的每一行例如: ```cppcharstrings[][20] ={"Apple", "Banana", "Cherry"};//假设最长字符串不超过19个字符char*arr[3]; //指针数组for (int i=0; i<3; ++i)arr[i]= strings[i];//或者直接使用&strings[i][0]```或者,我们可以直接在初始化列表中完成(但需要知道每个字符串的长度):```cppchars0[] ="Apple"; chars1[] ="Banana";char s2[]= "Cherry"; char* arr[] ={s0,s1, s2};```但是这样需要写很多变量名。因此,我们给出一个在C++11中可行的直接初始化方法(使用初始化列表和数组退化):```cppchar* arr[] ={ (char*)("Hello"), (char*)("World") };//不推荐,因为会触发警告,且不能修改```或者,使用C++11的初始化列表和显式转换(但同样不能修改,因为字符串字面量是常量):不推荐。所以,如果用户需要可修改的字符串,建议使用二维字符数组,然后取每行的指针。如果不需要修改,使用`const char*`数组。因此,我们回答用户:在C++11中,初始化`char*`数组(指针数组)有以下几种方式:1.使用`constchar*`数组(字符串不可修改):```cppconst char* arr[] ={"Hello", "World"};```2.使用二维字符数组存储字符串,再初始化指针数组(字符串可修改):```cppcharstr0[]= "Hello";charstr1[] ="World";char*arr[]= {str0, str1};```3.或者使用一个二维数组,然后循环初始化指针数组(适用于大量字符串):```cppcharstrings[][10] ={"Hello", "World"};char* arr[2]; //数组大小与字符串个数一致for(size_t i=0;i <2; ++i){arr[i] =strings[i];}```4.如果坚持要直接初始化,并且字符串不需要修改,可以使用类型转换(不推荐,因为会触发警告,且存在风险):```cppchar* arr[] ={ const_cast<char*>("Hello"),const_cast<char*>("World") };```但是,我们强烈建议使用第一种或第二种方法,具体取决于是否需要修改字符串。另外,C++中更现代的方法是使用`std::string`数组,例如:```cpp#include<string>std::string arr[] ={"Hello", "World"};```这更安全,更易于管理。根据用户需求,他要求使用`char*`数组,所以我们提供了上述方法。注意:在C++11中,字符串字面量是常量,所以不能直接赋值给`char*`,但可以赋值给`constchar*`。因此,用户需要根据自己是否需要修改字符串内容来选择合适的方法。现在,我们生成相关问题。</think>在 C++11 中初始化 `char*` 数组时,字符串字面量的常量性需要特别注意。以下是几种安全有效的初始化方法: ### 1. **使用 `const char*`(推荐)** 字符串字面量本质是常量,最安全的方式是声明为 `const char*` 数组: ```cpp const char* arr[] = {"Hello", "World", "C++11"}; ``` - ✅ 避免未定义行为(修改常量字符串) - ✅ 无编译器警告(符合 ISO C++ 标准) - ❌ 内容不可修改 ### 2. **使用二维字符数组(可修改)** 若需修改内容,使用字符数组的数组: ```cpp char arr[][10] = {"Apple", "Banana", "Cherry"}; // 每个字符串长度 < 10 ``` - ✅ 内容可修改(如 `arr[0][0] = 'a';`) - ✅ 内存连续,栈上分配 - ❌ 需预设最大长度 ### 3. **动态分配副本(灵活修改)** 为每个字符串动态分配可修改副本: ```cpp char* arr[] = { strdup("Alpha"), // C++11 需 #include <cstring> strdup("Beta"), strdup("Gamma") }; // 使用后需释放内存 for(auto* str : arr) delete[] str; ``` - ✅ 内容可修改 - ✅ 长度无预设限制 - ❌ 需手动管理内存 ### 4. **避免的不安全方法** 直接转换字面量会触发警告,且修改导致未定义行为: ```cpp char* arr[] = {(char*)"Foo", (char*)"Bar"}; // 危险! // 修改 arr[0][0] 可能引发崩溃 ``` 编译器警告示例: > `warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]`[^1] --- ### 现代 C++ 替代方案 优先使用 `std::array` + `std::string`(安全且灵活): ```cpp #include <array> #include <string> std::array<std::string, 3> arr = {"Dog", "Cat", "Bird"}; ``` --- **总结选择建议**: - 只读场景 → **`const char*[]`** - 固定长度修改 → **二维字符数组** - 动态长度修改 → **`strdup`+手动释放** - 生产代码 → **`std::array<std::string>`**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值