前端学习C语言 - 初级指针

这篇具有很好参考价值的文章主要介绍了前端学习C语言 - 初级指针。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

初级指针

本篇主要介绍:指针和变量的关系、指针类型、指针的运算符、空指针和野指针、指针和数组指针和字符串、const 和指针、以及gdb 调试段错误

基础概念

指针是一种特殊的变量。存放地址的变量就是指针。

int num = 1; 会申请4个字节的内存来存放数字1,每次访问 num 就是访问这4个字节。

访问内存中的这4个字节,不仅可以通过名称(例如 num),还可以通过地址

Tip& 不仅是位运算符,还是取地址操作符。例如 int* ptr = #,就是取变量 num 的地址并将其保存到指针变量 ptr 中

请看示例:

#include <stdio.h>

int main() {
    int num = 10;

    // num 的地址:0x7fff4dbf01d8
    printf("num 的地址:%p\n", &num);
    // num 的地址加1 :0x7fff4dbf01dc。
    printf("num 的地址加1 :%p\n", &num + 1);

    // j 存放连续内存的第一个字节地址
    int *j = &num;

    // 10。通过地址访问
    printf("%d", *j);

    return 0;
}

&num&num + 1 相差4个字节,说明 &num 表示整数。

普通变量存放值,而指针用于存放地址。

通过 int *j = &num 将变量num的首地址给到指针 j(j的类型是 int *),最后通过地址(*j) 访问整数1。

int *j 是一个int类型的指针,还有 char、float等指针类型。指针类型必须匹配,比如将 j 的指针类型换成 char,则会警告。就像这样:

- int *j = &num;
+ char *j = &num;

运行:

/workspace/CProject-test/main.c:12:11: warning: incompatible pointer types initializing 'char *' with an expression of type 'int *' [-Wincompatible-pointer-types]
    char *j = &num;
          ^   ~~~~
1 warning generated.
num 的地址:0x7ffddcfe5328
num 的地址加1 :0x7ffddcfe532c
10

Tip: 指针 j 也有地址,也就是指针的指针。现在不研究

练习

题目:请问输出什么?

#include <stdio.h>

int main() {
    int num = 10;
    int *p = &num;
    printf("用指针访问数据 num :%d\n", *p);

    *p = 11;
    printf("用过指针修改 num 数据:%d\n", num);

    return 0;
}

提示:数据可以通过变量访问,也能使用地址(指针)访问。就像通知同学去嵌入式实验室上课,或者是 303 上课。其中*p = 11; 等价于 num = 11;

输出:

用指针访问数据 num :10
用过指针修改 num 数据:11

星号的作用

指针 * 有两个主要作用(根据* 前面有无类型做区分):

  • 指针类型声明
  • 取值(又称解引用操作符)。例如,*ptr 表示获取指针变量 ptr 所指向内存地址上的值。

请看示例:

#include <stdio.h>

int main() {
    int num = 10;
    // 指针类型声明
    int *p = &num;

    // 取值
    printf("%d\n", *p); // 10

    // 取值
    *p = 11;
    printf("%d\n", num); // 11

    return 0;
}

指针类型

所占字节

在32位系统上,指针通常占用4个字节;而在64位系统上,指针通常占用8个字节。请看示例:

#include <stdio.h>

int main() {
    printf("char类型指针所占字节数为:%zu\n", sizeof(char*));
    printf("short类型指针所占字节数为:%zu\n", sizeof(short*));
    printf("int类型指针所占字节数为:%zu\n", sizeof(int*));
    printf("long类型指针所占字节数为:%zu\n", sizeof(long*));
    printf("float类型指针所占字节数为:%zu\n", sizeof(float*));
    printf("double类型指针所占字节数为:%zu\n", sizeof(double*));
    printf("long long类型指针所占字节数为:%zu\n", sizeof(long long*));
    return 0;
}

输出:

char类型指针所占字节数为:8
short类型指针所占字节数为:8
int类型指针所占字节数为:8
long类型指针所占字节数为:8
float类型指针所占字节数为:8
double类型指针所占字节数为:8
long long类型指针所占字节数为:8

练习

题目:请问整数类型的指针和字符类型的指针加1分别是几个字节?

#include <stdio.h>

int main() {
    int num = 10;

    printf("num 的地址:%p\n", &num);
    printf("num 的地址加1 :%p\n", &num + 1);

    char ch = 'a';

    printf("ch 的地址:%p\n", &ch);
    printf("ch 的地址加1 :%p\n", &ch + 1);
    return 0;
}

输出:

num 的地址:0x7fffe8244288
num 的地址加1 :0x7fffe824428c
ch 的地址:0x7fffe8244287
ch 的地址加1 :0x7fffe8244288

答案int * 加1是4个字节;char * 加1是1个字节。&num 和 &ch 分别代表该变量的全部字节。

指针交换数据

比如这段代码是不能实现 a、b 两数交换。请看示例:

#include <stdio.h>

void swap(x, y){
    int tmp = x;
    x = y;
    y = tmp;
}
int main() {
    int a = 1;
    int b = 2;
    swap(a, b);
    printf("a:%d\n", a);
    printf("b:%d\n", b);
    return 0;
}
a:1
b:2

分析:调用 swap(a, b) 这里是一个值传递,找到函数入口地址,对参数 x、y 申请空间和赋值,通过 tmp 变量完成了 x和y的交换,最后回收局部变量 x、y和tmp,释放空间。而 a,b数据没有变化。

可以通过指针来实现两数的交换。请看示例:

#include <stdio.h>

void swap(int* x, int* y){
    int tmp = *x;
    *x = *y;
    *y = tmp;
}
int main() {
    int a = 1;
    int b = 2;
    swap(&a, &b);
    printf("a:%d\n", a);
    printf("b:%d\n", b);
    return 0;
}
a:2
b:1

分析:通过 swap(&a, &b) 将 a b 的地址传给 x 和 y,通过 x 和 y 指针对 a 和 b 进行交换,虽然最后会销毁swap中的局部变量,但 a 和 b的值已经完成了交换。

指针的运算符

指针和变量的关系

练习1

题目:输出什么?

#include <stdio.h>

int main() {
    int a = 10, *pa = &a, *pb;
    printf("%d\n", *pa);
    pb = pa;
    printf("%d\n", *pb);
    return 0;
}

输出:10 10

分析:


int a = 10, 
// pa 指向变量 a
*pa = &a, 
// 定义一个整数型的指针 pb
*pb;
printf("%d\n", *pa);

// pb 也指向变量 a
pb = pa;
printf("%d\n", *pb);
return 0;

练习2

题目:输出什么?

#include <stdio.h>

int main() {
    int x = 3, y = 0, *px = &x;

    y = *px + 5;
    printf("%d\n", y);

    y= ++*px;
    printf("%d\n", y);

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

    y = *px++; 
    printf("%p\n", px);
    printf("%d\n", y);

    return 0;
}

输出:

8
4
0x7ffc48b9be38
0x7ffc48b9be3c
4

分析:

  • y= ++*px; 等效 ++(*px)。如果是 ++* 是不对的
类似 y = ++i,等于先执行 ++,在执行 y = i,
这里先对 (*px) 执行 ++,在返回  *px 的值
  • y = *px++;
先执行 y = *px,然后是 px++。px是整数类型的地址,加1就是加4个字节。

练习3

题目:输出什么?

#include <stdio.h>

int main() {
    int x = 3, y = 0, *px = &x;
    printf("%p\n", px);
    y = (*px)++; 
    printf("%p\n", px);
    printf("%d\n", x);

    return 0;
}

输出:

0x7ffef1dc4d58
0x7ffef1dc4d58
4

分析:*px++ 表示指针加1,(*px)++ 表示值加1。

指针初始化

指针初始化有两种方法:已经存在的空间和自己申请空间。

已经存在的空间,例如:

#include <stdio.h>
#include <stdlib.h>
int main() {
    int num;
    int* p = &num;
    *p = 10;

    char *str = "abc";
    printf("%s\n", str); // abc。把字符串的地址赋值给指针变量
    return 0;
}

自己申请空间可以使用 malloc 函数。申请的是 void 类型指针,也称为通用类型指针。请看示例:

#include <stdio.h>
// malloc 需要引入 <stdlib.h>
#include <stdlib.h>
int main() {
    // 申请16个字节
    int* q = malloc(sizeof(int) * 4); // 在堆里申请了16个字节
    // int* q = (int *)malloc(sizeof(int) * 4); // 推荐
    
    *q = 10;
    // 释放申请的16个字节
    free(q);
    return 0;
}

申请空间,使用完需要使用 free() 释放。

Tip:根据 C99 标准以及更高版本的标准,显式的类型转换是建议的做法,以确保类型的安全性和可读性。

空指针和野指针

下面这段代码 p 就是一个野指针,运行报错:段错误 (核心已转储)

#include <stdio.h>

int main() {
    int* p;
    *p = 1;
    return 0;
}

这里声明一个指针 p,里面是一个随机数,例如 0x7ffe71df3f40,接着往指向的内存放1,由于这块内存不知道是否存在,即使存在也不能访问,于是报段错误

直接手写一个地址也不可以。就像这样:

#include <stdio.h>

int main() {
    
    // warning: incompatible integer to pointer conversion initializing 'int *' with an expression of type 'long' [-Wint-conversion]
    // 这个警告是因为你正在将一个 long 类型的表达式赋值给一个 int* 类型的指针变量,导致类型不匹配。
    // int* p = 0x7ffe71df3f40;
    int* p = (int *)0x7ffe71df3f40;
    *p = 100;
    return 0;
}
// 分段错误 (核心已转储)"
Segmentation fault (core dumped)

空指针也不能使用:

int* p = NULL;
*p = 100;

// 输出:`Segmentation fault (core dumped)`

但空指针会让你可控。就像这样:

int* p = NULL;

if (p != NULL) {
    printf("p is not NULL\n");
}else{
    printf("p is NULL\n");
}

// 输出:p is NULL

指针和数组

指针当数组用

遍历一个数组,可以这样:

#include <stdio.h>

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int length = sizeof(arr) / sizeof(arr[0]);  // 计算数组的长度
    // 1 2 3 4 5 
    for (int i = 0; i < length; ++i) {
        printf("%d ", arr[i]);
    }

    return 0;
}

使用指针遍历数组有两种方式(效果相同)。请看示例:

#include <stdio.h>

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int length = sizeof(arr) / sizeof(arr[0]);  // 计算数组的长度

    // 指针遍历方式1
    /*
    int* pArr = arr;
    for (int i = 0; i < length; ++i) {
        printf("%d ", *(pArr + i));
    }
    */

    // 指针遍历方式2
    int* pArr = arr;
    for (int i = 0; i < length; ++i) {
        printf("%d ", pArr[i]);
    }

    return 0;
}

Tip:在数组一文中我们知道数组名表示首元素地址,这里*(pArr + i)会依次遍历数组或许是因为指针是int类型吧!

总结pArr[i] 等于 *(pArr + i)。在这里[]不再是取某个索引,而是表示取值。

指针和字符数组

题目:分析 char a[] = "Hello";char *b = "World";

  • 都可以用for遍历元素。例如:
#include <stdio.h>

int main() {
    char a[] = "Hello";
    char *b = "World";

    // Iterating over 'a'
    printf("Characters in 'a':\n");
    for (int i = 0; a[i] != '\0'; i++) {
        printf("%c\n", a[i]);
    }

    // Iterating over 'b'
    printf("\nCharacters in 'b':\n");
    for (int i = 0; b[i] != '\0'; i++) {
        printf("%c\n", b[i]);
    }

    return 0;
}

输出:

开始运行...

Characters in 'a':
H
e
l
l
o

Characters in 'b':
W
o
r
l
d

运行结束。
  • 为什么指针也可以通过索引访问特定字符?
    比如 char *b = "World";,可以将字符串视为字符数组,使用指针来指向该数组的首地址,指针可以通过偏移来访问特定位置的元素,包括字符串中的字符。

练习

题目:下面代码中 p1[0]p2[0]p3[0]的值分别是多少?

// 申请4*4个字节,每个字节地址假如是:0x100(存放1) 0x104(存放2) 0x108 0x10c
int a[] = {1,2,3,4};

int *p1 = (int*)(&a + 1);

int *p2 = (int*)((int)a + 1);

int *p3 = (int*)(a + 1);

分析:

  • (int*)(&a + 1) - &a 表示整个数组,加1则到下一个数组,然后将数组指针强转成整数指针,指向第5个元素,其实已经越界了。
  • (int*)((int)a + 1) - a 表示数组首元素地址,(int)a 将地址转为整数,以前是加1个元素,现在就是加1,然后又将整数转为整数指针,乱了(就好比访问 0x101 0x102 0x103 0x104
  • (int*)(a + 1) - a 表示数组首元素地址,加1则是第二个元素地址 0x104,不强转也可以。

结论:只有p3[0](等价于 *(p3 + 0))是一个正常的元素,也就是2.

指针和字符串

题目:用数组和指针定义字符串有什么区别?

#include <stdio.h>

int main() {
    char str[] = "HelloWorld";
    // HelloWorld
    printf("%s\n", str);

    char* s = "HelloWorld";
    // HelloWorld
    printf("%s\n", s);

    return 0;
}

Tip: 字符串的输出都是首地址,比如这里的 str 是数组的首地址,s 指针指向的也是首地址。

分析:
char str[] = "HelloWorld"; 在栈中定义一个数组,用11个字节存储HelloWorld(还有一个 \0)。请看示例:

#include <stdio.h>

int main() {
    char str[] = "HelloWorld";
    str[0]++; 
    // IelloWorld
    printf("%s\n", str); 
    // error: cannot increment value of type 'char[11]'
    str++;
    // printf("%s\n", str);
    return 0;
}

数组名(str++)不可以修改,str 就是数组首元素地址,已经固定了,可认为它是常量。但数组内容可以修改。

char* s = "helloWorld";helloWorld 放在只读数据区,s 是局部变量,放在栈中,占8个字节。请看示例:

#include <stdio.h>

int main() {
    char* s = "helloWorld";
    
    s++;
    // elloWorld
    printf("%s\n", s);

    // 报错:Segmentation fault (core dumped)
    s[0]++;

    return 0;
}

指针可以加加,但指针指向的内容不能修改。

str 只是个名字,不占空间,如果一定要说占多少,那就是它执行的数组占11个字节。而 s 是8个字节,指向一个只读区,占 11 个字节。

练习

题目:分析以下示例。

#include <stdio.h>

int main() {
    char str[20];
    str = "HelloWorld";

    char* s;
    s = "HelloWorld";
    // HelloWorld
    printf("%s\n", s);

    return 0;
}

分析:

// 分配20个字节的内存,并把首地址给 str
char str[20];
// str 是只读的,不能再赋值。报错:`error: array type 'char[20]' is not assignable`
str = "HelloWorld";

// 定义一个指针 s
char* s;
// 将 HelloWorld 的首地址给 s
s = "HelloWorld";

扩展

自定义strcpy()函数

题目:实现原生字符串拷贝方法strcpy。strcpy 其用法如下:

#include <stdio.h>
#include <string.h>

int main() {
    char source[] = "Hello";
    char destination[10]; // 目标字符串需要足够的空间来容纳 source 字符串

    strcpy(destination, source);

    printf("Source string: %s\n", source);
    printf("Destination string: %s\n", destination);

    return 0;
}

实现:

#include <stdio.h>

char* strcpy_custom(char* destination, const char* source) {
    // 字符串数组末尾有一个特殊的空字符 '\0' 来表示字符串的结束。逐个复制字符,直到遇到源字符串的结束标志 '\0'
    while (*source != '\0') {
        *destination = *source;
        destination++;
        source++;
    }

    *destination = '\0'; // 在目标字符串末尾添加结束标志 '\0'

    return destination;
}

int main() {
    // 定义两个字符数组
    char source[] = "Hello";
    char destination[10]; // 目标字符串需要足够的空间来容纳 source 字符串

    // 数组名。表示首元素的地址,加 1 是加一个元素(比如这里1个字节)
    strcpy_custom(destination, source);

    printf("Source string: %s\n", source);
    printf("Destination string: %s\n", destination);

    return 0;
}

Tipconst char* source 中 const 的作用请看const 和指针

输出:

开始运行...

Source string: Hello
Destination string: Hello

运行结束。

将 while 替换成下面一行代码效果也相同:

char* strcpy_custom(char* destination, const char* source) {
    /*
    while (*source != '\0') {
        *destination = *source;
        destination++;
        source++;
    }

    *destination = '\0'; 
    */

    // 替换成
    while((*destination++ = *source++) != '\0');
    return destination;
}

分析:(*destination++ = *source++) != '\0':

之前的是首先判断,在赋值。`*source != '\0'`、`*destination = '\0';`,这里是先赋值

后置++会放在表达式最后,所以等于:

(*destination = *source) != '\0';
destination++;
source++;

const 和指针

首先补充下(int*)的作用。之前说到 const 定义的变量可以被修改,我们写了如下代码:

#include <stdio.h>

int main() {
    const int val =5;

    int *ptr= (int*)&val;
    *ptr=10;

    printf("val = %d\n",val);
    printf("*ptr = %d\n", *ptr);

    return 0;
}

其中 int *ptr= (int*)&val; 是将一个 const int 类型的变量 val 地址强制转换为 int* 类型的指针,并将指针存储在 ptr 中。这种类型转换是不安全的,因为它丢失了 val 的常量性质。

const char* source 声明一个常量指针,以下代码仅做示意:

#include <stdio.h>

int main() {
    const char* source = "Hello";
    char* mutableSource = "World";

    printf("%c\n", source[0]);
    printf("%c\n", mutableSource[0]);

    // 以下操作是非法的,会导致编译错误
    // source[0] = 'h'; // 不能修改字符数据

    // 合法
    // 尽管mutableSource是一个非常量指针,看起来可以进行修改,但修改字符串常量是不被允许的,并且这可能导致未定义行为。
    mutableSource[4] = 'w'; // 可以修改字符数据
    return 0;
}

运行:

开始运行...

H
W
Segmentation fault (core dumped)

运行结束。
就近原则

const 有个就近原则

  • 比如:const int* p1 = &num;,const 修饰的是 *,所以 *p1 不能修改, p1 可以修改
  • 比如:int* const p2 = &num;,const 修饰 p2,所以 p2 不能修改,*p2 可以修改

请看示例:

#include <stdio.h>

int main() {
    int num = 1;
    const int* p1 = &num; // const 修饰的是 *,所以 *p1 不能修改, p1 可以修改

    p1++;
    // (*p1)++;

    int* const p2 = &num; // const 修饰 p2,所以 p2 不能修改,*p2 可以修改

    // p2++;
    (*p2)++;

    const int* const p3 = &num; // 两个都不能修改
    // p3++;
    // (*p3)++;

    return 0;
}

gdb 调试段错误

GDB(GNU Debugger)是一款强大的调试器,用于帮助开发者查找和解决程序中的错误。通过与源代码交互,并提供诸如断点设置、变量观察、内存检查等功能,GDB允许开发者逐行执行程序并分析其运行状态。
除了上文使用的 run,还有如下操作

  • run:运行程序。
  • break <line_number>:在指定行设置断点。
  • break <function_name>:在指定函数设置断点。
  • continue:继续执行程序直到下一个断点或程序结束。
  • next:逐过程地执行程序。
  • step:逐语句地执行程序。
  • print <variable>:打印变量的值。
  • backtrace:显示函数调用的堆栈跟踪信息。
  • quit:退出GDB调试会话。

使用 gdb 调试段错误的过程如下:

编写代码:

pjl@pjl-pc:~/pjl$ cat demo-3.c
#include <stdio.h>

int main() {
    int* p;
    *p = 1;

    return 0;
}

编译运行发现段错误:

pjl@pjl-pc:~/pjl$ gcc demo-3.c -o demo-3
pjl@pjl-pc:~/pjl$ ./demo-3
段错误 (核心已转储)

将代码编译为可调试的可执行文件。在gcc或g++编译时,添加"-g"选项可以生成包含调试信息的可执行文件。

// 增加 -g
pjl@pjl-pc:~/pjl$ gcc demo-3.c -o demo-3 -g

// 启动GDB并加载可执行文件
pjl@pjl-pc:~/pjl$ gdb demo-3
GNU gdb (Ubuntu 9.1-0kylin1) 9.1
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from demo-3...

(gdb) 

输入 run(还有其他操作) 找到是第5行代码报错:

...
// run:运行程序。
(gdb) run
Starting program: /home/pjl/pjl/demo-3

Program received signal SIGSEGV, Segmentation fault.
0x0000555555555135 in main () at demo-3.c:5
5           *p = 1;
(gdb)

高级指针

提前透露:指针遇上数组

题目:以下代码输出什么?

#include <stdio.h>

int main() {
    char * string[] = {"Hello", "World" };
    printf("%s\n", string);
    return 0;
}

分析:
我们知道定义字符串有以下两种方法:

char str[] = "HelloWorld";
char* s = "HelloWorld";

Tip: string 在 C 中不是关键字,也不是保留字,就是一个普通变量名。

[] 的优先级是非常高的,这里首先是定义一个数组(string[]),其次就是指针,合起来就是一个指针数组。

首先在只读区分配两块内存分别存放 Hello(地址比如是 0x100) 和 World(地址比如是 0x200),指针数组是16个字节,本质就是数组,只不过里面放的是指针,比如前8个字节的地址是0x1000,那么 string 就是 0x1000,因为数组名就是数组首元素地址。

所以要输出这两个字符串,可以这么写:文章来源地址https://www.toymoban.com/news/detail-499547.html

#include <stdio.h>

int main() {
    char * string[] = {"Hello", "World" };

    // Hello
    printf("%s\n", string[0]);
    // World
    printf("%s\n", string[1]);
    return 0;
}

到了这里,关于前端学习C语言 - 初级指针的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言学习系列-->看淡指针(3)

    在指针的类型中我们知道有⼀种指针类型为字符指针 char* 一般使用: 进阶使用 本质是把字符串 hello ⾸字符的地址放到了pstr中。 把⼀个常量字符串的⾸字符 h 的地址存放到指针变量 pstr 中。 经典例题: 运行结果: 这⾥str3和str4指向的是⼀个同⼀个常量字符串。C/C++会把常量

    2024年02月11日
    浏览(36)
  • C语言指针入门学习、知识点梳理(四)

    本篇内容:指针星号的三种含义以及指针在函数调用时,与实参、形参的变量传递关系,如何通过被调函数修改主调函数普通变量的值。 传送门: C语言指针入门学习、概念梳理(一) C语言指针入门学习、概念梳理(二) C语言指针入门学习、知识点梳理(三) C语言指针入门

    2024年02月09日
    浏览(31)
  • C语言学习(二十五)---指针练习题(一)

    在上一节内容中,我们学习了 递归 与 冒泡排序法 的有关内容,今天我们将继续往下学习,主要内容为 指针练习题 ,好了,话不多说,开整!!! 在之前的第18—22的内容中,我们学习了 指针 的一系列内容,今天我们对之前的 指针内容进行测试 ,在查看答案之前,请先自

    2024年02月10日
    浏览(30)
  • C语言-指针进阶-qsort函数的学习与模拟实现(9.3)

    目录 思维导图: 回调函数 qsort函数介绍 模拟实现qsort 写在最后: 什么是回调函数? 回调函数是一个通过函数指针调用的函数。 将一个函数指针作为参数传递给一个函数,当这个指针被用来调用所指向函数时, 我们就将此称为回调函数。 在举例之前,我们先学习一个C语言

    2024年02月15日
    浏览(41)
  • C/C++|物联网开发入门+项目实战|指针|嵌入式C语言高级|C语言内存空间的使用-学习笔记(9)

    参考: 麦子学院-嵌入式C语言高级-内存空间 内存类型资源地址、门牌号的代名词 指针:地址的代名词 指针变量:存放指针这个概念的盒子 *P char *p *p; C语言娟译器对指针这个特殊的概念,有2个疑问? 1、分配一个盒子,盒子要多大? 在32bit系统中,指针就4个字节 2、盘子里存放

    2023年04月22日
    浏览(42)
  • 前端学习C语言 - 开篇

    前端学习C语言有很多理由:工作、兴趣或其他。 C 语言几个常见的使用场景: 操作系统 开发:Linux 操作系统的内核就是主要由 C 语言编写的。其他操作系统也广泛使用 C 语言进行核心部分的开发。 系统级开发和嵌入式编程:C 语言具有强大的 底层 控制能力和高效的代码执

    2024年02月08日
    浏览(24)
  • 1+x web前端开发初级理论答案+解析(一)

    目录 一、单选题(每小题2分,共30小题,共60分) 二、多选题(每小题2分,共15小题,共30分) 三、判断题(每小题2分,共5小题,共10分。在每小题后对应括号内填入判断结果,正确的选项填写“√”,错误的选项填写“×”) 1、在HTML中,(  C  )用来表示特殊字符引号 A、

    2024年02月08日
    浏览(30)
  • web前端1+x(初级)理论(158道单选题含答案)

    1、以下关于在CSS中的选择器命名错误的是(B) A..boxp B. %div C.* D.table 2、给某段文字设置穿过文本的一条线,应该设置什么属性?(A) A. text-decoration B.text-align C.text-indent D.text-transform 3、关于引入样式的优先级说法正确的是(  C )。 A.内联样式!important内部样式外部样式

    2024年02月06日
    浏览(27)
  • 初级web前端开发工程师的岗位职责描述(合集)

      初级web前端开发工程师的岗位职责描述1 职责: 1. 根据功能需求设计编写页面原型; 2. 前后端联调保证功能流畅; 3. 提高页面易用性、美观提出合理建议。 4、与后台工程师配合开发联调并交付产品; 5、持续优化前端页面体验和访问速度,保证页面精美高效。 任职要求 1、

    2024年02月14日
    浏览(32)
  • 前端学习C语言 - 数组和字节序

    本篇主要介绍: 一维二维数组 、 字符数组 、 数组名和初始化注意点 以及 字节序 。 初始化 有以下几种方式对数组初始化: Tip :以上写法创建的数组都是 不可变大小的 。 练习1 题目 : int a[5] = {1} ,请问 a 的每个值是多少? 输出: 1 0 0 0 0 。 在C和C++中,当我们创建数组

    2024年02月09日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包