关于使用C/C++柔性数组的一些坑

8 篇文章 0 订阅
6 篇文章 0 订阅

一、问题来源

之前有看到C/C++中的柔型数组(又叫变长数组)(又叫0长数组),据说好处多得很,但一直没有机会用到,今天突发奇想用这个柔性数组重写之前的一些代码(毕竟之前的想法:不好用定长数组的场合只能用链表模拟实现)。

二、问题描述

使用柔性数组后,发现出现了很多问题,接下来我就好好描述一下我遇到的问题,其中删除了部分没有用到的代码:

问题:循环出错。插入出错。查询出错

代码:

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

typedef struct {
	int length;  //总长度
	int cursor;  //下一个要插入元素的位置
	int data[0];
}order_table;

order_table create_order_table(int length);  //创建一个柔性数组
void insert_order_table_element(order_table *table, int element);  //向柔性数组里添加元素
void binary_search(order_table table, int element);  //查找有序表中的元素

int main(void)
{
	int table_length;
	int table_index;
	int element;

	printf("Please enter the length of the ordered table:\n");
	scanf("%d", &table_length);
	order_table table = create_order_table(table_length);

	printf("Please enter the elements of the ordered table:\n");
	for (table_index = 0; table_index < table_length; table_index++)
	{
		printf("table's total length is %d, now insert index is %d\n", table_length, table_index);
		scanf("%d", &element);
		insert_order_table_element(&table, element);
	}

	for(table_index=0;table_index<table.length;)
	{
		printf("search index:%d, address:%p\n", table_index, &(table.data[table_index]));
		printf("%d\n", table.data[table_index]);
		table_index += 1;
	}

	printf("Please enter the element which you want to search:\n");
	scanf("%d", &element);
	binary_search(table, element);
}

order_table create_order_table(int length)
{
	order_table* table = (order_table*)malloc(sizeof(order_table) + sizeof(int)*length);
	table->length = length;
	table->cursor = 0;
	return *table;
}

void insert_order_table_element(order_table *table, int element)
{
	printf("\ninsert before:%d, address:%p\n", table->cursor, &(table->data[table->cursor]));
	table->data[table->cursor] = element;
	printf("insert element:%d\n", element);
	(table->cursor)++;
	printf("insert after:%d\n", table->cursor);
}

void binary_search(order_table table, int element)
{
	int temp_index;
	int low = 0, high = table.length, middle;
	int key;
	while (low <= high)
	{
		middle = (low + high) / 2;
		key = table.data[middle];
		printf("binary_index:%d, key:%d\n", middle, key);
		if (key == element)
		{
			printf("Search successful, it's in %d element\n", middle);
			return;
		}
		else if (table.data[middle] < element)
			low = middle + 1;
		else
			high = middle - 1;
	}
	printf("Search failed\n");
}

结果1:????恕我书读的少,想不明白这个错误,插入时的地址和查询是的地址一样,但是值怎么不对。。而且为啥是1,2,3,5,5。。不应该是1,2,3,4,5吗?
在这里插入图片描述
结果2: ennnn,好像哪里不对,输入了5个值后为什么没有跳出来,还能继续输入。。。
在这里插入图片描述

结果3: 忽然间我想到了一点,会不会是redhat7的原因呢?不支持柔型数组?于是我换了centos8来测试,但是????????????说好的循环5次呢?而且也没有插进去值呀。
在这里插入图片描述
。。。。。。。。。。。。。总之遇到了很多莫名其妙问题,有一些因为我解决问题尝试的次数太多,已经不知道怎么复现了,不过就这三个问题应该能展现出来问题的奇葩性吧。

三、问题的解决

因为柔型数组的特性:即最后一个元素不占结构体总的大小。所以在传递时无法选择值传递的方式(即使这个函数的功能是查询,出于避免误操作数据的原因,并不希望将数据的地址传进去)。最后的解决办法是:一定要选择地址传递的方式,一定要选择地址传递的方式,一定要选择地址传递的方式。 说三遍都不足以表达我内心中跑过的羊驼数量。
测试地址的代码:

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

typedef struct {
	int length;
	int cursor;
	int data[0];
}order_table;

order_table* create_order_table(int length);  //创建一个柔性数组
void check_order_table_length(order_table table, int *length);  //返回柔性数组的长度
void free_order_table(order_table *table);  //释放柔性数组的内存
void insert_order_table_element(order_table *table, int element);  //向柔性数组里添加元素
void binary_search(order_table table, int element);  //查找有序表中的元素

int main(void)
{
	int table_length;
	int table_index;
	int element;

	printf("Please enter the length of the ordered table:\n");
	scanf("%d", &table_length);
	order_table *table = create_order_table(table_length);

	printf("Please enter the elements of the ordered table:\n");
	for (table_index = 0; table_index < table_length; table_index++)
	{
		scanf("%d", &element);
		printf("table_length:%d, insert before table_index:%d\n", table_length, table_index);
		insert_order_table_element(table, element);
		printf("table_length:%d, insert after table_index:%d\n", table_length, table_index);
	}

	for(table_index=0;table_index<table->length;)
	{
		printf("search index:%d, address:%p\n", table_index, &(table->data[table_index]));
		printf("%d\n", table->data[table_index]);
		table_index += 1;
	}

	printf("Please enter the element which you want to search:\n");
	scanf("%d", &element);
	binary_search(*table, element);
}

order_table* create_order_table(int length)
{
	order_table* table = (order_table*)malloc(sizeof(order_table) + sizeof(int)*length);
	table->length = length;
	table->cursor = 0;
	printf("in create_order_table:%p\n", table);
	return table;
}

void check_order_table_length(order_table table, int *length)
{
	*length = table.length;
}

void free_order_table(order_table *table)
{
	free(table);
	table = NULL;
}

void insert_order_table_element(order_table *table, int element)
{
	printf("in insert_order_table_element:%p\n", table);
	printf("\ninsert before:%d, address:%p\n", table->cursor, &(table->data[table->cursor]));
	table->data[table->cursor] = element;
	printf("insert element:%d\n", element);
	(table->cursor)++;
	printf("insert after:%d\n", table->cursor);
}

void binary_search(order_table table, int element)
{
	printf("in binary_search:%p\n", table);
	int temp_index;
	int low = 0, high = table.length, middle;
	int key;
	int i;
	for (i=0;i<table.length;i++)
	{
		printf("i:%d ", i);
		printf("value:%d  ", table.data[i]);
		printf("address:%p\n", &(table.data[i]));
	}
}

测试地址结果: 可以看到binary_search函数中各个数据的地址都是错误的,值也是错误的。

[root@localhost /]# ./main 
Please enter the length of the ordered table:
5
in create_order_table:0x10d5ac0
Please enter the elements of the ordered table:
1 2 3 4 5
table_length:5, insert before table_index:0
in insert_order_table_element:0x10d5ac0

insert before:0, address:0x10d5ac8
insert element:1
insert after:1
table_length:5, insert after table_index:0
table_length:5, insert before table_index:1
in insert_order_table_element:0x10d5ac0

insert before:1, address:0x10d5acc
insert element:2
insert after:2
table_length:5, insert after table_index:1
table_length:5, insert before table_index:2
in insert_order_table_element:0x10d5ac0

insert before:2, address:0x10d5ad0
insert element:3
insert after:3
table_length:5, insert after table_index:2
table_length:5, insert before table_index:3
in insert_order_table_element:0x10d5ac0

insert before:3, address:0x10d5ad4
insert element:4
insert after:4
table_length:5, insert after table_index:3
table_length:5, insert before table_index:4
in insert_order_table_element:0x10d5ac0

insert before:4, address:0x10d5ad8
insert element:5
insert after:5
table_length:5, insert after table_index:4
search index:0, address:0x10d5ac8
1
search index:1, address:0x10d5acc
2
search index:2, address:0x10d5ad0
3
search index:3, address:0x10d5ad4
4
search index:4, address:0x10d5ad8
5
Please enter the element which you want to search:
4
in binary_search:0x500000005
i:0 value:1  address:0x7fff261f67f0
i:1 value:0  address:0x7fff261f67f4
i:2 value:0  address:0x7fff261f67f8
i:3 value:0  address:0x7fff261f67fc
i:4 value:639592512  address:0x7fff261f6800
[root@localhost /]# 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值