#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef void SeqList;
typedef void SeqListNode;
typedef unsigned int TSeqListNode;
typedef unsigned int TSeqListNode;
typedef struct _tag_SeqList
{
int capacity;
int length;
TSeqListNode *node;
}TSeqList;
SeqList * SeqList_Create(int capacity)
{
TSeqList *ret = NULL;
if(capacity>=0)
{
ret = (TSeqList *)malloc(sizeof(TSeqList) sizeof(TSeqListNode)*capacity);
}
if(ret == NULL)
{
printf("malloc fail.\n");
exit(-1);
}
ret->capacity = capacity;
ret->length = 0;
ret->node = (TSeqListNode*)(ret 1);
return ret;
}
int SeqList_Insert(SeqList *list, SeqListNode *node, int pos)
{
TSeqList *sList = (TSeqList*)list;
int ret = (sList != NULL);
int i = 0;
ret = ret && (sList->length 1 <= sList->capacity);
ret = ret && (0 <= pos);
if(ret)
{
if(pos >= sList->length)
{
pos = sList->length;
}
for(i=sList->length; i > pos; i--)
{
sList->node[i] = sList->node[i-1];
}
sList->node[i] = (TSeqListNode)node;
sList->length ;
}
return ret;
}
int main()
{
system("pause");
return 0;
}
D:\mingw64\bin\gcc.exe -g D:\Cpp\DSA\test001.c -o D:\Cpp\test001.exe
D:\Cpp\test001.c: In function 'SeqList_Insert':
D:\Cpp\test001.c:56:26: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
sList->node[i] = (TSeqListNode)node;
^
CodePudding user response:
What you are trying to do is already part of the ISO/IEC 9899:1999 C standard. It's called flexible array member. So no need for inventing your own code - just use what is already available.
Also notice that capacity and length are variables that can't be negative. So you should use an unsigned type. The common used type would be size_t
.
So your code should be:
typedef struct _tag_SeqList
{
size_t capacity;
size_t length;
TSeqListNode node[]; // Flexible array member
} TSeqList;
Now you can simply do:
ret = malloc(sizeof(TSeqList) sizeof(TSeqListNode)*capacity);
\--------------/ \----------------------------/
Memory for the Memory for the 'node' array
struct, i.e for with 'capacity' elements
capacity and
length
to allocate (no need for checking the value of capacity
as it can't be negative).
And just use node
as a normal array.
All the need for casts are gone.
CodePudding user response:
Earlier versions of the C standard (C90) probably do necessitate casting. I think a placeholder data (int *)(array 1)
is entirely appropriate in some situations, assuming alignment is respected. Note that you might also make this design decision to comply with MISRA C 2012 Rule 18.7. I have eliminated the obfuscating typedef
s and renamed parts of it to reflect what it actually does more clearly. A cast to void *
is basically turning off type-checking, (through a typedef
or not,) and should be avoided where possible.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct IntArray {
size_t capacity;
size_t length;
int *node;
};
/** @throws[malloc] */
static struct IntArray *IntArray_Create(const size_t capacity)
{
struct IntArray *ret = NULL;
ret = malloc(sizeof *ret sizeof *ret->node * capacity);
if(ret == NULL) return 0; /* Let the caller decide what to do. */
ret->capacity = capacity;
ret->length = 0;
ret->node = (int *)(ret 1);
return ret;
}
/** Returns false if the `array` is full or null. Clips `pos` to `array`. */
static int IntArray_Insert(struct IntArray *array, const int node, size_t pos)
{
if(!array || array->length >= array->capacity) return 0;
if(pos >= array->length) pos = array->length;
/* Replaced looping over the array for performance. */
memmove(array->node pos 1, array->node pos, array->length - pos);
array->length ;
array->node[pos] = node;
return 1;
}
#include <assert.h>
int main(void)
{
struct IntArray *a;
if(!(a = IntArray_Create(3))) { perror("fail"); return EXIT_FAILURE; };
assert(IntArray_Insert(a, 1, 42));
assert(IntArray_Insert(a, 3, 1));
assert(IntArray_Insert(a, 2, 1));
assert(!IntArray_Insert(a, 2, 1));
free(a);
return 0;
}
If you are targeting C99
or later, the flexible array member may be useful for this exact reason. If this is part of a macro, the only typedef
you really need is typedef int ArrayType;
.