- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我需要将一些 uint32_t 和 uint16_t 数字放入 char* 中。然后我需要从缓冲区中取回它们。
我已经阅读了一些问题,并尝试使用 sprintf 将它们放入 char* 中,然后 sscanf 再次获取原始数字。但是,我无法正确获取它们。
这是我的代码示例,只有 2 个数字。但我需要超过 2 个,这就是我使用 realloc 的原因。另外,我不知道如何通过 uint16_t 正确使用 sprintf 和 sscanf
uint32_t gid = 1100;
uint32_t uid = 1000;
char* buffer = NULL;
uint32_t offset = 0;
buffer = realloc(buffer, sizeof(uint32_t));
sprintf(buffer, "%d", gid);
offset += sizeof(uint32_t);
buffer = realloc(buffer, sizeof(uint32_t) + sizeof(buffer));
sprintf(buffer+sizeof(uint32_t), "%d", uid);
uint32_t valorGID;
uint32_t valorUID;
sscanf(buffer, "%d", &valorGID);
buffer += sizeof(uint32_t);
sscanf(buffer, "%d", &valorUID);
printf("ValorGID %d ValorUID %d \n", valorGID, valorUID);
我得到的是
ValorGID 11001000 ValorUID 1000
我需要得到的是
ValorGID 1100 ValorUID 1000
我是 C 的新手,所以任何帮助将不胜感激。
最佳答案
buffer = realloc(buffer, sizeof(uint32_t));
sprintf(buffer, "%d", gid);
offset += sizeof(uint32_t);
buffer = realloc(buffer, sizeof(uint32_t) + sizeof(buffer));
sprintf(buffer+sizeof(uint32_t), "%d", uid);
这真的没有意义,除非在幸运的情况下,否则不会按预期工作。
让我们假设通常的 CHAR_BIT == 8
成立,所以 sizeof(uint32_t) == 4
.此外,让我们假设 int
是一个带符号的 32 位整数,采用二进制补码表示,没有填充位。
sprintf(buffer, "%d", gid)
打印 gid
的位模式的十进制字符串表示形式解释为 int
缓冲。在上述假设下,gid
被解释为介于 -2147483648 和 2147483647 之间的数字。因此,十进制字符串表示可能包含 '-'
, 包含 1 到 10 个数字和 0 终止符,总共使用 2 到 12 个字节。但是你只分配了四个字节,所以每当999 < gid < 2^32-99
(带符号的二进制补码解释为 > 999
或 < -99
),sprintf
写入超过分配的缓冲区大小。
这是未定义的行为。
它可能不会立即崩溃,因为分配四个字节通常会有效地为您提供更大的内存块(例如 malloc
总是返回 16 字节对齐的 block ,分配的四个字节后面的十二个字节不能被其他部分使用的程序,但属于程序的地址空间,并且写入它们可能不会被发现)。但是当分配的 block 的末尾位于页面边界时,它很容易在以后崩溃。
此外,由于您将后续的 sprintf
的写入偏移量提前了四个字节s,如果字符串表示(不包括 0 终止符)使用超过四个字节(同时程序还没有因写入未分配的内存而崩溃),则前一个数字的一部分将被覆盖。
线
buffer = realloc(buffer, sizeof(uint32_t) + sizeof(buffer));
包含更多错误。
buffer = realloc(buffer, new_size);
如果 realloc
,则丢失对已分配内存的引用并导致泄漏失败。使用临时文件并检查是否成功
char *temp = realloc(buffer, new_size);
if (temp == NULL) {
/* reallocation failed, recover or cleanup */
free(buffer);
exit(EXIT_FAILURE);
}
/* it worked */
buffer = temp;
/* temp = NULL; or let temp go out of scope */
新尺寸sizeof(uint32_t) + sizeof(buffer)
新分配的数量始终相同,sizeof(uint32_t) + sizeof(char*)
.这通常是 8 或 12 个字节,因此在分配的区域之外写入并导致崩溃或内存损坏(这可能会在很久以后导致崩溃)不需要很多数字。
您必须跟踪分配给buffer
的字节数并用它来计算新的尺寸。没有(可移植的)方法来确定从指针到其开始的已分配内存块的大小。
现在的问题是您是想在缓冲区中存储字符串表示形式还是位模式。
存储字符串表示存在字符串表示的长度随值变化的问题。因此,您需要在数字表示之间包含分隔符,或者在必要时通过填充(使用空格或前导零)确保所有表示具有相同的长度。例如,这将像
#include <stdint.h>
#include <inttypes.h>
#define MAKESTR(x) # x
#define STR(x) MAKESTR(x)
/* A uint32_t can use 10 decimal digits, so let each field be 10 chars wide */
#define FIELD_WIDTH 10
uint32_t gid = 1100;
uint32_t uid = 1000;
size_t buf_size = 0, offset = 0;
char *buffer = NULL, *temp = NULL;
buffer = realloc(buffer, FIELD_WIDTH + 1); /* one for the '\0' */
if (buffer == NULL) {
exit(EXIT_FAILURE);
}
buf_size = FIELD_WIDTH + 1;
sprintf(buffer, "%0" STR(FIELD_WIDTH) PRIu32, gid);
offset += FIELD_WIDTH;
temp = realloc(buffer, buf_size + FIELD_WIDTH);
if (temp == NULL) {
free(buffer);
exit(EXIT_FAILURE);
}
buffer = temp;
temp = NULL;
buf_size += FIELD_WIDTH;
sprintf(buffer + offset, "%0" STR(FIELD_WIDTH) PRIu32, uid);
offset += FIELD_WIDTH;
/* more */
uint32_t valorGID;
uint32_t valorUID;
/* rewind for scanning */
offset = 0;
sscanf(buffer + offset, "%" STR(FIELD_WIDTH) SCNu32, &valorGID);
offset += FIELD_WIDTH;
sscanf(buffer + offset, "%" STR(FIELD_WIDTH) SCNu32, &valorUID);
printf("ValorGID %u ValorUID %u \n", valorGID, valorUID);
具有零填充的固定宽度字段。如果您更愿意使用分隔符而不是固定宽度,则所需长度和偏移量的计算会变得更加复杂,但除非数字很大,否则它会使用更少的空间。
如果您更愿意存储位模式,这将是最紧凑的存储方式,您可以使用类似
size_t buf_size = 0, offset = 0;
unsigned char *buffer = NULL, temp = NULL;
buffer = realloc(buffer, sizeof(uint32_t));
if (buffer == NULL) {
exit(EXIT_FAILURE);
}
buf_size = sizeof(uint32_t);
for(size_t b = 0; b < sizeof(uint32_t); ++b) {
buffer[offset + b] = (gid >> b*8) & 0xFF;
}
offset += sizeof(uint32_t);
temp = realloc(buffer, buf_size + sizeof(uint32_t));
if (temp == NULL) {
free(buffer);
exit(EXIT_FAILURE);
}
buffer = temp;
temp = NULL;
buf_size += sizeof(uint32_t);
for(size_t b = 0; b < sizeof(uint32_t); ++b) {
buffer[offset + b] = (uid >> b*8) & 0xFF;
}
offset += sizeof(uint32_t);
/* And for reading the values */
uint32_t valorGID, valorUID;
/* rewind */
offset = 0;
valorGID = 0;
for(size_t b = 0; b < sizeof(uint32_t); ++b) {
valorGID |= buffer[offset + b] << b*8;
}
offset += sizeof(uint32_t);
valorUID = 0;
for(size_t b = 0; b < sizeof(uint32_t); ++b) {
valorUID |= buffer[offset + b] << b*8;
}
offset += sizeof(uint32_t);
¹ 如果你知道怎么做 malloc
等在您的实现中工作,可能会从 malloc
中找到大小的簿记数据。
关于从 uint32/16_t 创建一个字符串,然后解析回原始数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11425817/
我有以下代码 unsigned int headerbytes = 0U; headerbytes = (unsigned int*)strtoull(packet_space->header
我有这段无法编译的代码: public struct MyStruct { private fixed uint myUints[32]; public uint[] MyUints
在 Go 中,从函数返回哪个更有效:返回 uint 还是返回 *uint? 该函数在 cpu 密集型库的内部 for 循环中调用。 最佳答案 一般来说,只要效率是个问题,您就应该运行基准测试。 让我们
int 加上 unsigned int 返回一个 unsigned int。应该这样吗? 考虑这段代码: #include #include #include class test {
我正在尝试从可通过 URL 访问的内容中初始化一个字符串: actualresponse.response = String(contentsOfURL: url, usedEncoding: NSU
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 提供事实和引用来回答它. 1年前关闭。 Improve this
我从函数 Swift 得到类型为 UnsafeMutablePointer 的结果 我可以把它转换到UInt吗? ? 最佳答案 只需使用memory 属性来访问底层数据。 let ptr: Unsaf
我深入了解了 List并发现了以下代码: public T this[int index] { get { // Following trick can red
我在 this page on bit twiddling 的帮助下编写了这个函数: uint16_t *decode(uint64_t instr) { // decode instr (thi
我正在从微 Controller 读取两个寄存器。一个具有 4 位 MSB(前 4 位有一些其他内容),另一个具有 8 位 LSB。我想将其转换为一个 12 位 uint(准确地说是 16 位)。到目
要演示的示例代码: public int FindComplement(int num) { //uint mask = ~0; //<-- error CS0031 //
$ rustc --test mapAsMapKey.rs mapAsMapKey.rs:18:43: 18:52 error: mismatched types: expected `fn@(&&@
一般问题:我有一个很大的二维点空间,里面稀疏地分布着点。把它想象成一 block 撒满黑点的白色大 Canvas 。我必须多次迭代和搜索这些点。 Canvas (点空间)可能很大,接近极限int 的值
假设我们只是调用一个普通数字,数字会启动什么。 uint256 plainNumber 我明白它是零。但是我要问的是,有没有办法检测该数字是由编译器还是用户变量设置的。例如... uint256 pl
我试图在 leetcode.com ( https://leetcode.com/problems/number-of-1-bits/ ) 上解决一个简单的问题,我遇到了一个奇怪的行为,这可能是我缺乏
uint number = 0x418 in bits : 0000010000011000 uint number1 = 0x8041 in bits: 1000000001000001 uint
我如何在 C# 中生成具有某个最大值的伪随机 uint? (不需要最低限度。)似乎有很多问题要求完全随机,但没有上限。 澄清:此上限可能大于 int.MaxValue,因此仅强制转换 Random.N
我已经用私有(private)数据成员围绕 ulong 编写了一个简单的包装器。我希望能够将包装器转换为 ulong 以检索数据。我希望强制转换为 uint 并丢失数据是非法的,因此我没有编写对 ui
哪些是“Uint”变量?就是有“Uint8”、“Uint16”等…… 但是它们是什么? 现在我有一些时间使用 C++,但我从来不需要使用这些变量并引起我的好奇。 提前致谢。 最佳答案 uint 不是标
我有一个 native 方法,它需要一个指针来写出一个双字(uint)。 现在我需要从 (Int) 指针中获取实际的 uint 值,但是 Marshal 类只有方便的方法来读取(有符号)整数。 如何从
我是一名优秀的程序员,十分优秀!