C语言提高_01

C语言指针与内存详解
本文详细介绍了C语言中的数组地址、内存区域划分、字符串常量存储位置、指针的概念及其使用技巧等内容,并通过具体示例展示了如何利用指针进行间接赋值,实现了跨函数的数据传递。

1.c语言中数组的地址是数组取地址(&)

例如:int a[];     打印a和&a结果是相同的。但是打印a+1和&a+1结果就不同了,&a+1是跳过整个数组大小到下一个地址。

2.c应用开启的时候,系统会开辟四块内存区域:堆区 ,栈区,全局区(静态区,常量区),方法区


下面举例子说明:


字符串常量是在全局区中的,也就是当函数出栈的时候,字符串常量没有被析构掉,可以正常使用。

经电话语:指针指向谁就吧谁的地址赋值给指针。指针变量和他指向的内存空间变量是两个不同的概念。

上述中的两个函数中的局部变量指针指向的 都是一个字符串地址,如果这个两个字符串相同,c++编译器会做代码优化处理只会保留一份。所有说打印的地址是通过的。

栈的生长方向和buf的生长方向是两个不同的概念。


3. 指针的强化

指针也是一种数据类型,有内存大小,可以赋值。
*p放在等号的左边   写内存
*p放在等号的右边   读内存。
常量区的内存不能通过指针去修改,不然会报错。例如:char * p=“alsdkfj”;  *(p+2)=M;就会报错。   p为字符串的首地址,+2的话就到了第三个地址的位置。
野指针是指针指向了一块被回收的内存空间。一般free后,需要对指针进行赋NULL操作。


4.通过指针间接赋值的意义

再函数调用的时候,形参传给实参,用实参取地址,传给形参,在被调用函数里面用*p,来改变实参,把运算结果传出去。
指针作为函数参数的精髓,c语言的特有现象,c语言的精华
void getdata(int* n,char** m)
{
	int q=0;
	char* w=NULL;
	w=(char*)malloc(100);
	strcpy(w,"assdfggghgh");

	*m=w;
	*n=strlen(w);
}
int main(void)
{
	int a=0;
	char* b=NULL;
	getdata(&a,&b);
	
}
这里a和b就是入参出参,在两个函数中都可以操作同一块内存,实现逻辑的分层处理。

间接赋值成立的三个条件:
1. 定义1一个变量(实参)    定义一个变量(形参)
2. 建立关联:把实参取地址传给形参
3.形参去间接的修改实参的值。
使用场景:
1 2 3条件写在一个函数中
12写在一块,3单独写在另一个函数中
1          23写在一块,,,,在C++中会使用到。



### 关于C语言实现GB28181客户端的相关资料 为了使非标准设备能够接入GB28181平台,通常需要开发一套基于C语言的客户端程序来模拟GB28181协议的行为。以下是一个简单的示例代码框架,用于展示如何通过C语言实现GB28181客户端的核心功能。 #### 1. 初始化SIP栈并注册到GB28181服务器 GB28181协议基于SIP(会话发起协议),因此初始化SIP栈是第一步。以下是创建SIP消息并向GB28181服务器发送REGISTER请求的一个简单例子: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define SIP_SERVER "sip:server.example.com" #define USER_AGENT "CustomGB28181Client" void send_register_request(const char *from, const char *to) { printf("Sending REGISTER request to %s\n", SIP_SERVER); // 构造REGISTER消息体 char register_message[512]; snprintf(register_message, sizeof(register_message), "REGISTER %s SIP/2.0\r\n" "Via: SIP/2.0/UDP client.example.com;branch=z9hG4bK776sgklf\r\n" "Max-Forwards: 70\r\n" "From: <%s>;tag=12345abcde\r\n" "To: <%s>\r\n" "Call-ID: abcdefg@example.com\r\n" "CSeq: 1 REGISTER\r\n" "User-Agent: %s\r\n" "Contact: <sip:%s@client.example.com>\r\n" "Expires: 3600\r\n" "Content-Length: 0\r\n\r\n", SIP_SERVER, from, to, USER_AGENT, from); // 假设这里有一个函数send_sip_message负责实际发送数据包 // send_sip_message(register_message); } int main() { const char *device_id = "sip:deviceid@example.com"; send_register_request(device_id, device_id); return 0; } ``` 上述代码展示了如何构建一个基本的`REGISTER`请求,并将其发送至指定的GB28181服务器[^1]。 --- #### 2. 处理实时音视频流传输 (RTP) 除了SIP信令外,GB28181还涉及媒体流的传输,这通常是通过RTP(实时传输协议)完成的。下面是一段伪代码,说明如何设置RTP会话并发送音视频帧: ```c #include <stdint.h> typedef struct RtpPacket { uint8_t version : 2; /* RTP版本 */ uint8_t padding : 1; /* 填充标志 */ uint8_t extension : 1; /* 扩展头部标志 */ uint8_t csrc_count : 4; /* CSRC计数器 */ uint8_t marker : 1; /* 标记位 */ uint8_t payload_type : 7; /* 负载类型 */ uint16_t sequence_number; /* 序列号 */ uint32_t timestamp; /* 时间戳 */ uint32_t ssrc; /* 同步源ID */ } RtpHeader; void send_rtp_packet(RtpHeader *header, void *payload, size_t payload_size) { printf("Sending RTP packet with seq=%u and ts=%u\n", header->sequence_number, header->timestamp); // 这里假设存在一个网络层接口用于发送RTP数据包 // send_network_data((uint8_t *)header, sizeof(*header), payload, payload_size); } int main() { RtpHeader rtp_header = { .version = 2, .padding = 0, .extension = 0, .csrc_count = 0, .marker = 0, .payload_type = 96, .sequence_number = 1, .timestamp = 0, .ssrc = rand() }; // 创建虚拟负载数据 uint8_t test_payload[] = { 0x01, 0x02, 0x03 }; send_rtp_packet(&rtp_header, test_payload, sizeof(test_payload)); return 0; } ``` 此部分实现了基础的RTP头结构定义以及发送逻辑。 --- #### 3. 使用第三方库简化开发流程 如果不想完全手动实现SIP和RTP协议细节,可以选择一些成熟的开源库作为辅助工具。例如,PJSIP 是一种广泛使用的多媒体通信库,它提供了对SIP的支持;libsrtp 则专注于安全化的RTP处理。这些库可以帮助开发者快速搭建起GB28181兼容的应用环境[^2]。 --- ### 总结 以上分别介绍了利用纯C语言手写方式达成GB28181客户终端的功能模块设计思路及其对应的部分核心算法片段。对于更复杂的场景,则建议引入专门针对此类需求优化过的外部依赖项以减少重复劳动量的同时提高稳定性与性能表现。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值