字符串数组的三种形式

article/2025/10/31 12:30:06

一、字符串数组

1.0 字符串数组的两种形式

  1. 第一种形式:二维字符数组
char arry[7][10] = {"Monday","Tuesday","Wednsday","Thurday","Friday","Saturday","Sunday"};
  • 在栈上分配了70字节内存,字符串数组有7个元素,每个元素是10个字节的字符数组,因为数组名arry是指向数组首元素arry[0]的指针,arry[0]的类型是char [10],所以arry的类型是char (*arry)[10],知道arry类型很重要,当把arry作为函数参数传递时要注意,1.2小节中有示例。
  • 反过来我们可以定义char (*myarry)[10] 类型的指针来指向char myarry[][10]的字符串数组,即char (*myarry)[10] = arry。
  1. 第二种形式:字符指针数组
char* arry[] = {"chen","chun","xia","baob"}; 

在栈上分配了sizeof(char*)*4字节的内存空间,存储字符串指针,因为数组名arry是指向数组首元素arry[0]的指针,arry[0]的类型是char*,所以arry的类型就是char** arry(等价于char* (*arry)),在1.1小节有示例。

反过来我们可以定义char **myarry 类型的指针来指向一段内存空间(用malloc,char **myarry = (char **)malloc(sizeof(char)*num)),用来存储字符串地址,或者将char* arry[]类型的字符串数组地址赋给它,即char **myarry = arry。

⚠️注意这两种字符串数组的数组名的类型不能混用,根本原因在于字符串数组的首元素类型不同。

1.1 字符串在只读区,字符串地址在栈区

字符串数组char* arry[]在栈上申请空间,存储字符串地址,字符串实际是存储在只读存储区,在排序时交换的是字符串地址。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>void printStr(char** myarry,int lenght){for(int i = 0;i < lenght;i++)   printf("%s\n",*(myarry + i));
}void sortStr(char** arry,int lenght){char* tmp = NULL;// tmp = (char*)malloc(sizeof(char)*10);for(int i = 0;i < lenght;i++)for(int j = i+1;j<lenght;j++){if((strcmp(*(arry+i),*(arry+j))) > 0){tmp = *(arry+i);*(arry+i) = *(arry+j);*(arry+j) = tmp;}}
}int main(){char* arry[] = {"chen","chun","xia","baob"}; int lenght = sizeof(arry) / sizeof(arry[0]);printStr(arry,lenght);sortStr(arry,lenght);printStr(arry,lenght);  return 0;      
}

1.2 字符串在栈区

通过二维字符数组char arry[count][num]在栈上申请固定大小的内存块来存储字符串,排序交换的是内存块中的字符串值。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>#define count 7
#define num 10//void printArry(char myarray[][])
void printArry(char (*myarray)[num],int mycount)
{int i = 0;for(;i < mycount;i++)printf("%s\n",myarray[i]);//*(myarray + i)
}void sortArry(char (*myarray)[num],int mycount)
{int i = 0;int j = 0;char tmp[num] = {};for(;i < mycount;i++)for(j = i + 1;j < mycount;j++){if(strcmp(myarray[i],myarray[j]) > 0){strcpy(tmp,myarray[i]);strcpy(myarray[i],myarray[j]);strcpy(myarray[j],tmp);}}
}int main()
{char arry[count][num] = {"Monday","Tuesday","Wednsday","Thurday","Friday","Saturday","Sunday"};printArry(arry,count);sortArry(arry,count);printArry(arry,count);return 0;
}

1.3字符串数组在堆区

通过char** ptr = (char**)malloc(sizeof(char*) * num);在堆上申请了sizeof(char*) * num)个字节来放指针,又通过循环将栈上array数组中的字符串指针拷贝到堆上ptr[i],

#include <stdio.h>
#include <string.h>
#include <stdlib.h>#define num 12void printfArray(char** myarray,int count)
{int i = 0;for(;i < count; i++){printf("%s \n",myarray[i]);}
}void sortArray(char** myarray,int count)
{int i = 0;int j;char* tmp = malloc(sizeof(char*));for(;i < count; i++)for(j = i + 1;j< count;j++){if(strcmp(myarray[i],myarray[j])>0){tmp = myarray[i];myarray[i] = myarray[j];myarray[j] = tmp;}} 
}int main()
{int i = 0;char* array[] = {"Janaury","Febraury","March","April","May","June","July","August","september","October","Nevember","December"};char** ptr = (char**)malloc(sizeof(char*) * num);//指针ptr(即*ptr)可以看作是堆上的数组char* ptr[num]首元素ptr[0]的地址for(;i < num; i++){ptr[i] = array[i];//将栈上的字符串地址拷贝到堆空间上}printfArray(array,num);sortArray(array,num);printf("排序后\n");printfArray(array,num);return 0;
}

1.4 字符串数组在堆区2

#include <stdio.h>
#include <string.h>
#include <stdlib.h>#define num 12void printfArray(char (*myarray)[10],int count)
{int i = 0;for(;i < count; i++){printf("%s \n",myarray[i]);}
}void sortArray(char (*myarray)[10],int count)
{int i = 0;int j;char tmp[num] = {};for(;i < count; i++)for(j = i + 1;j< count;j++){if(strcmp(myarray[i],myarray[j])>0){strcpy(tmp,myarray[i]);strcpy(myarray[i],myarray[j]);strcpy(myarray[j],tmp);}} 
}int main()
{int i = 0;char array[][10] = {"Janaury","Febraury","March","April","May","June","July","August","september","October","Nevember","December"};char** ptr = (char**)malloc(sizeof(char*) * num);//指针ptr(即*ptr)可以看作是堆上的数组char* ptr[num]首元素ptr[0]的地址for(;i < num; i++){//ptr[i] = array[i];//将栈上的字符串地址拷贝到堆空间上ptr[i] = (char*)malloc(sizeof(char)*10);strcpy(ptr[i],array[i]);}printfArray(array,num);sortArray(array,num);printf("排序后\n");printfArray(array,num);return 0;
}

二、复习指针变量

所有变量的基本属性:变量名称,值,地址(分配内存后获得)

普通变量把 作为基本量,把地址作为通过‘&’运算符获得的派生量,而指针变量把 地址 作为基本量,把值作为通过‘*’运算符获得的派生量。——《C Primer Plus(第6版)中文版》P273

指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。 要搞清一个指针需要搞清指针的四方面的内容:指针的类型指针所指向的类型指针的值或者叫指针所指向的内存区、指针本身所占据的内存区。让我们分别说明。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2.1 指针的类型

从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。这是指针本身所具有的类型。让我们看看例一中各 个指针的类型:

(1)int* ptr; 指针的类型是 int*
(2)char* ptr; 指针的类型是 char*
(3)int** ptr; 指针的类型是 int**
(4)int(*ptr)[3]; 指针的类型是 int()[3]
(5)int*(*ptr)[4]; 指针的类型是 int
(*)[4]

2.2 指针所指向的类型

当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了 编译器将把那片内存区里的内容当做什么来看待。

从语法上看,你只须把指针声明语句中的指针名字和名字左边的指针声 明符*去掉,剩下的就是指针所指向的类型。例如:

(1)int*ptr; 指针所指向的类型是 int
(2)char*ptr; 指针所指向的的类型是 char
(3)int**ptr; 指针所指向的的类型是 int*
(4)int(*ptr)[3]; 指针所指向的的类型是int()[3]
(5)int*(*ptr)[4]; 指针所指向的的类型是 int*()[4]

在指针的算术运算中,指针所指向的类型有很大的作用。指针的类型(即指针本身的类型)和指针所指向的类型是两个概念。当你对 C 越来越熟悉时,你会发现,把与指针搅和在一起的"类型"这个概念分成"指针的类型"和"指针所指向的类型"两个概念,是精通指针的关键点之一。我看了不少书,发现有些写得差的书中,就把指针的这两个概念搅在一起了,所以看起书来前后矛盾,越看越糊涂。

2.3 指针的值 或者 叫指针所指向的内存区

指针的值是指针本身存储的数值,这个值将被编译器当作一个地址,而不是一个一般的数值。在 32 位程序里,所有类型的指针的值都是一个 32 位整数,因为 32 位程序里内存地址全都是 32 位长。 指针所指向的内存区就是从指针的值所代表的那个内存地址开始,长度为 si zeof(指针所指向的类型)的一片内存区。以后,我们说一个指针的值是 XX,就相当于说该指针指向了以 XX 为首地址的一片内存区域;我们说一个指针指向了某块内存区域,就相当于说该指针的值是这块内存区域的首地址。

指针所指向的内存区和指针所指向的类型是两个完全不同的概念。在例 一中,指针所指向的类型已经有了,但由于指针还未初始化,所以它所指向 的内存区是不存在的,或者说是无意义的。

以后,每遇到一个指针,都应该问问:这个指针的类型是什么?指针指 的类型是什么?该指针指向了哪里?(重点注意)

2.4 指针本身所占据的内存区

指针本身占了多大的内存?你只要用函数 sizeof(指针的类型)测一下 就知道了。在 32 位平台里,指针本身占据了 4 个字节的长度。指针本身占据的内存这个概念在判断一个指针表达式(后面会解释)是 否是左值时很有用。

参考文章:指针的本质—如何确定指针的类型


http://chatgpt.dhexx.cn/article/ohgRyQs2.shtml

相关文章

干货丨什么是字符串数组

一、概念理解 1.C语言中没有字符串类型&#xff0c;用一片内存空间保存一串字符&#xff0c;这片空间称作字符数组。 2.以‘\0’结尾的字符数组被称为字符串数组。‘\0’是字符串结束的标志。 3.用双引号括起来的都是字符串。 二、初始化 char str[6] {h,e,l,l,o,\0};//字…

c语言之字符串数组

还是在写图的存储结构的时候&#xff0c;遇到了问题&#xff0c;就是如何在一个数组中存放字符串&#xff0c;我相信这个问题 对于面向对象的编程语言来说&#xff0c;轻而易举&#xff0c;比如对于Java来说,直接像下面就可以了&#xff1a; 但是c语言没有String这个类型&…

Android 自定义弹窗提示(AlertDialog)

Android 自定义弹窗提示 Java文件&#xff1a; private void showDialog() {AlertDialog.Builder builder new AlertDialog.Builder(this);//获取界面View view LayoutInflater.from(this).inflate(R.layout.alert_dialog, null);//将界面填充到AlertDiaLog容器并去除边框bui…

AlertDialog对话框详例

Android—3分钟你也能学会AlertDialog对话框 在Android开发中&#xff0c;少不了AlertDialog对话框的使用&#xff0c;也是至关重要的一个功能。AlertDialog的构造方法被声明为protected&#xff0c;所以我们不能使用new来创建AlertDialog对象。 目录 Android—3分钟你也能学…

Android - AlertDialog 对话框

Android - AlertDialog 对话框 使用步骤&#xff1a; ①创建一个AlertDialog.Builder对象②设置标题 内容 正面负面按键 编写点击事件③调用.show() 显示AlertDialog XML部分&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLay…

AlertDialog替代ProgressDialog方案

在Android API level 26及以后版本中&#xff0c;ProgressDialog被弃用&#xff0c;使用以下方法可以替代ProgressDialog。 首先&#xff0c;使用AlertDialog新建一个对象作为容器&#xff0c;在这里我们首先设置对话标题&#xff0c;然后取消然后关闭返回键退出对话框&#x…

改变AlertDialog默认背景

安卓4.0自带的AlertDialog太丑了有木有&#xff1f;黑色的背景很难看&#xff0c;今天实现的是怎么自定义style实现改变AlertDialog背景 首先在values/styles.xml文件中增加如下style <style name"AlertDialog" parent"android:Theme.DeviceDefault.Light.…

Android App开发超实用实例 | AlertDialog对话框

介绍AlertDialog对话框从简到繁的多种设计方案,从新角度理解UI交互设计。 AlertDialog对话框允许自定义弹出对话框的内容,实现比之前讲解的几种对话框更丰富的功能。 01、带默认按钮的AlertDialog 程序单击按钮后执行第17行代码,调用自定义方法showAlertDialog()。 第22~6…

Android中AlertDialog的使用

Android中AlertDialog的使用 简述默认样式单选弹出框多选弹出框列表对话框自定义弹出框完整代码 简述 AlertDialog可以在当前的界面上显示一个对话框&#xff0c;这个对话框是置顶于所有界面元素之上的&#xff0c;能够屏蔽掉其他控件的交互能力&#xff0c;因此AlertDialog一般…

android-如何关闭AlertDialog.Builder对话框

android-如何关闭AlertDialog.Builder对话框 前言 在实际写代码的时候&#xff0c;AlertDialog.Builder的使用算是比较频繁的&#xff0c;在对AlertDialog.Builder关闭的时候&#xff0c;我们会发现&#xff0c;AlertDialog.Builder对话框没有相对应的finish()或者dismiss()这…

Android 自定义AlertDialog

Android 自定义popuWindow 对于项目需求中&#xff0c;系统的弹出框不能满足我们的需求&#xff0c;就只能通过自定义布局来实现自己相对应的功能&#xff0c;这里总结一篇关于AlertDialog的 具体操作 这里把弹出框封装了一个方法&#xff0c;使用的时候&#xff0c;只需要在…

Android进阶之AlertDialog自定义

AlertDialog的自定义方式有很多种&#xff0c;这里介绍两种。 第一种是比较简单的&#xff0c;只自定义内容。 在AlertDialog使用详解中&#xff0c;非常详细的介绍了以下六种使用方法。 一、简单的AlertDialog&#xff08;只显示一段简单的信息&#xff0c;比如about us&…

Android入门第九篇之AlertDialog

本文来自http://blog.csdn.net/hellogv/ &#xff0c;引用必须注明出处&#xff01; 时隔一年&#xff0c;又要准备做Android的开发了&#xff0c;最近复习和整理一下Android的知识。这次要说的是AlertDialog&#xff0c;这种对话框会经常遇到。AlertDialog跟WIN32开发中的Dial…

对话框AlertDialog的基本使用(新手)

AlertDialog是点击某一组件时&#xff0c;本文用按钮举例&#xff0c;弹出一个对话框&#xff0c;供你选择接下来的操作。 基础用法 首先要给按钮设置点击事件&#xff0c;然后再onClick里构建 AlertDialog.Builder 方法 代码如下&#xff1a; findViewById(R.id.btn).setOn…

Android的 AlertDialog自定义布局与常用布局用法(弹窗)

1.直接上效果图&#xff0c;看看是不是你们想要的效果图 2.主活动MainActivity2的代码如下 import androidx.appcompat.app.AppCompatActivity; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.app…

AlertDialog详解

对话框介绍与示例 对话框在程序中不是必备的&#xff0c;但是用好对话框能对我们编写的应用增色不少。采用对话框可以大大增加应用的友好性。比较常用的背景是&#xff1a;用户登陆、网络正在下载、下载成功或者失败的提示&#xff0c;还有&#xff0c;比如&#xff1a;短信来了…

Android的AlertDialog详解

转自&#xff1a;http://www.2cto.com/kf/201205/131876.html 参考文章&#xff1a;http://www.cnblogs.com/jiezzy/archive/2012/09/20/2694917.html http://blog.csdn.net/lizzy115/article/details/6924416 AlertDialog的构造方法全部是Protected的&#xff0c;所以不能直接…

AndroidStudio中AlertDialog的四种用法

目录 1.默认样式 2.单选弹出框 3.多选弹出框 4.自定义弹出框 补充&#xff01;&#xff01; 1.默认样式 android.support.v7.app.AlertDialog.Builder builder new android.support.v7.app.AlertDialog.Builder(AlertDialogActivity.this); builder.setTitle("请回…

Android之AlertDialog的基础使用

坦白说&#xff0c;AlertDialog我在工作中用得并不多&#xff0c;因为AlertDialog的样式比较固定和呆板&#xff0c;为了和App的整体设计匹配&#xff0c;一般都是使用自定义的Dialog&#xff0c;只有在要求不高时用一下。但是作为Android的基础控件之一&#xff0c;掌握它是十…

安卓AlertDialog弹窗

Android在开发中经常会遇到有弹框的需求。 经常使用的有Dialog 弹框&#xff0c;Window弹框&#xff08;任意位置弹出除了外观样式和显示的位置的区别之外&#xff0c;他们之间最本质的区别是&#xff1a; dialog是非阻塞式对话框&#xff0c;popupwindow是阻塞式对话框。也就…