C fat pointer implementation failure - c

I have discovered a library recently which implements a C++ vector like functionality using fat pointers.
I have tried to replicate a similar behaviour in a short program (see the code below). I can access the array elements fine but when I try to get the number of elements my program prints garbage.
#include <stdio.h>
#include <stdlib.h>
int main()
{
double * a = NULL;
// the data
double b[] = {1, 2, 3, 5};
a = (int *) malloc(sizeof(int) + sizeof(double *));
a[0] = 4;
a++;
a = b;
// will print 1.0 2.0 3.0 5.0
printf("%lf %lf %lf %lf\n", a[0], a[1], a[2], a[3]);
// prints garbage
printf("%d\n", *((int *) a - 1));
// this will fail
free(((int *) a - 1))
return 0;
}
It is likely that the problem lies in the pointer arithmetic part of the code, i.e. (int *) a - 1 points to the wrong address, but I could not figure out why is that the case.
Any help is appreciated.

Packing the length at the beginning of the array is not a fat pointer, but an ill-formed PASCAL array.
int main(fat_pointer);
int main(int argc, char* argv[argc]); // standard signature for main is a fat pointer
A fat pointer is a pointer and an index. The data type of the index is an integral type which guarantees that sizeof index <= sizeof(size_t). In other words, sizeof(int) <= sizeof(size_t) is a mandate for all compliant hosted environment because main demands so. Note that size_t is not defined for freestanding environment.
The problem with _s functions is that they use sal.h from Microsoft which allow the usage of variables before declaration.
char * strcpy_s(char * restrict dest, rsize_t destsz, char const * restrict src);
// fat pointer form fails
char * strcpy_s(char dest[destsz], rsize_t destsz, char const * src);
The fat pointer form fails because destsz is declared afterwards, so it cannot be used. Annex K is horrible because it has usage before declaration in fat pointer form. Look at main where argc is declared before argv; that is the proper way to declare a fat pointer.
#include<stdio.h>
#include<stdlib.h>
void print_vector_double(int len, double d[len])
{
for (int i = 0; i < len; i++)
printf("%lf ", d[i]);
printf("\n");
printf("%d\n", len);
}
int main(int argc, char* argv[argc])
{
// C89 VLA - initialized VLA
double b[] = { 1, 2, 3, 5, };
int b_len = (int)(sizeof b / sizeof b[0]);
print_vector_double(b_len, b);
// C99 VLA - uninitialized VLA
int c_len = b_len;
double c[c_len];
c = b;
print_vector_double(c_len, c);
// Good Old Heap for Dynamic Arrays
int a_len = b_len;
double * a = malloc(a_len * sizeof * a);
double * temp = memcpy(a, b_len * sizeof * b, b);
if (temp != a) exit(EXIT_FAILURE);
print_vector_double(a_len, a);
free(a), a = NULL, a_len = 0;
}
A fat pointer is what you pass to a function. If you are not passing anything to another function, there is no fat pointer.
Cello failed to understand what a fat pointer really is.

Related

How to make C functions agnostic to data type

I have been working on a simple library in C to handle arrays, dynamic arrays and linked lists. As a starting point I have been working on a function to pop a user defined index from an array. For starters I am working an an integer array and came upon this solution.
int pop_int_array(int *array, int index, int size) {
int type = sizeof(int);
if (index >= size) return 0;
unsigned char *dst = (unsigned char*) array + index + type;
memmove(dst, dst + type, type * (size - index - 1));
return 1;
}
int main(int argc, const char * argv[]) {
int a[5] = {1, 2, 3, 4, 5};
pop_int_array(a, 2, 5);
for (int i = 0; i < 4; i++) {
printf("%d\n", a[i]);
}
}
This yields the following output as expected
1
2
4
5
If I wanted to pop a float array, I would need to create a new function titled pop_float_array that copied all of the contents from pop_int_array but instead of using int type = sizeof(int) I would replace it with int type = sizeof(float), and of course the array data type would be a float instead of an int. However, this violates a core principle of software development by repeating the same code several times, where each time would be an implementation for a data type. In order to get around this I re-wrote the function in the following way where the array is declared as a void data type. In addition I cast the array to a void * in the main program before or during the process of passing it to the function.
int pop_array(void *array, int index, int size, int type) {
if (index >= size) return 0;
unsigned char *dst = (unsigned char*) array + index + type;
memmove(dst, dst + type, type * (size - index - 1));
return 1;
}
int main(int argc, const char * argv[]) {
int a[5] = {1, 2, 3, 4, 5};
pop_array((void *)a, 2, 5);
for (int i = 0; i < 4; i++) {
printf("%d\n", a[i]);
}
float b[5] = {1.1, 2.2, 3.3, 4.4, 5.5};
pop_array((void *)a, 2, 5);
for (int i = 0; i < 4; i++) {
printf("%f\n", a[i]);
}
}
As expected this yields
1
2
4
5
1.1
2.2
4.4
5.5
This allows me to only create and maintain one function. However, this seems so simple that I am surprised it is not a more widely used technique, or at least that I am aware of in my little experience. Is there some consequence of writing the function this was or casting the array to a void * that I am not seeing, or is this a legitimate way to make a function type agnostic in C?
The way you're doing this is fine. But you do have one mistake:
unsigned char *dst = (unsigned char*) array + index + type;
You're not moving up by the right amount. This should be:
unsigned char *dst = (unsigned char*) array + (index * type);
Also, you don't need to cast to void * when you call the function:
pop_array(a, 2, 5, sizeof(int));
This technique is used in the qsort function which can sort an array of an arbitrary type. It's signature is as follows:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
As with your function, it takes a void * to the start of the array as well as the number of elements and the size of each element. It also takes a function pointer whose job is to perform the type specific comparison.

Passing a multidimensional array as an argument in C

I am trying to initialize matrices in a helper function, but I am getting a warning accessing the matrix inside the helper function that I can't figure out how to fix. I was reading about multidimensional arrays and even saw the same notation used to pass and access a matrix in multiple examples, but mine generates a warning and I'm not quite sure why.
To my knowledge this error means that the argument is not of a type the function is expecting, but I was using it just fine inside the main function before relocating the initialization into its own function. This leads me to think that I'm doing something wrong when passing the matrix to the helper function.
passing argument 1 of 'memmove' makes pointer from integer without a cast [-Wint-conversion]
Here's my code for the initializer. p is a pointer to data inside an array that I want to initialize into my matrix. I'm using this type of nested for loop to spread 16 bytes of data coming from p into my matrix 1 byte per cell.
void initialize(const unsigned char *p, unsigned char (*matrix)[4]) {
for (unsigned int i = 0; i < 4; i++){
for (unsigned int j = 0; j < 4; j++){
memmove(matrix[i][j], p + (4*i+j), 1); <--- Warning here
};
};
};
Initialize is being called in another function like this:
void func(const unsigned char *p) {
unsigned char matrix[4][4] = {
{0x0,0x0,0x0,0x0},
{0x0,0x0,0x0,0x0},
{0x0,0x0,0x0,0x0},
{0x0,0x0,0x0,0x0}
};
initialize(p, matrix);
};
Function memmove() takes a pointer as the first argument. While matrix[i][j] is a char, a type from integer family. Assingning an integer other than constant 0 to a pointer require a cast. Otherwise a warning is raised.
Therefore I expect that in order to copy a single char you should pass a pointer to element matrix[i][j]. Pointers are formed by applying & operator to objects.
memmove(&matrix[i][j], p + (4*i+j), 1);
however it can written far simpler, more readable and likely more optimal as:
matrix[i][j] = p[4 * i + j];
or even by copying the whole array without any loops:
memmove(matrix, p, 16);
passing argument 1 of 'memmove' makes pointer from integer without a cast [-Wint-conversion]
Instead of passing an integer value as the destination:
unsigned char (*matrix)[4]
...
// v----------v This is an integer of type unsigned char
// memmove(matrix[i][j], p + (4*i+j), 1);
Pass the address of the integer as the destination:
memmove(&matrix[i][j], p + (4*i+j), 1);
// ^-----------^ This is an address
void *memmove(void *s1, const void *s2, size_t n); expects s1 to be an address.
matrix in func() is a matrix, aka "2-D array".
matrix in initialize() is not really a matrix, but a pointer to an array[4] of unsigned char.
Since C99 and selectively afterwards, code can use a variable length array notation.
void initialize(size_t rows, size_t cols, unsigned char (*m)[rows][cols],
const unsigned char *p) {
printf("%zu %zu %zu\n", rows, cols, sizeof *m);
for (size_t r = 0; r < rows; r++){
for (size_t c = 0; c < cols; c++){
(*m)[r][c] = *p++;
}
}
}
#define ROW 5
#define COL 7
int main(void) {
unsigned char matrix[ROW][COL];
unsigned char bytes[sizeof matrix] = "Something abcde fghij klmno pqrst uvwxy z";
size_t r = sizeof matrix / sizeof matrix[0];
size_t c = sizeof matrix[0] / sizeof matrix[0][0];
printf("%zu %zu %zu\n", r, c, sizeof matrix);
initialize(r, c, &matrix, bytes);
}

Regarding question about function pointer in C?

I was reading about function pointer. That it contains address of instructions. And there I encountered one question to find an element in array using function pointer. Here is the code.
#include <stdio.h>
#include <stdbool.h>
bool compare(const void* a, const void* b)
{
return (*(int*)a == *(int*)b);
}
int search(void* arr, int arr_size, int ele_size, void* x, bool compare(const void*, const void*))
{
char* ptr = (char*)arr; // Here why not int *ptr = (int*)arr;
int i;
for (i = 0; i < arr_size; i++)
{
if (compare(ptr + i * ele_size, x))
{
return i;
}
}
return -1;
}
int main()
{
int arr[] = { 2, 5, 7, 90, 70 };
int n = sizeof(arr) / sizeof(arr[0]);
int x = 7;
printf("Returned index is %d ", search(arr, n, sizeof(int), &x, compare));
return 0;
}
In the search function char *ptr = (char*)arr; is used which is giving perfect answer = 2.
But when I have used int *ptr = (int*)arr; it gives -1 as answer.
Why is this? Can anyone explain this?
A char is the smallest addressable unit in any C program, and on most system it corresponds to a single byte. That treats the array as a generic sequence of bytes, and uses the ele_size to calculate the byte-position of each element with ptr + i*ele_size.
If you use int *ptr then the byte-position calculation will be wrong by a factor of sizeof(int) (typically 4), since the pointer arithmetic will be done in units of the base type (int instead of char).
The function search knows nothing about what is the type of elements of the array pointed to by the pointer arr of the type void *.
So casting the pointer to the type int * does not make a sense. If to do so then the expression ptr + i*ele_size where the pointer arithmetic is used will produce an incorrect result.
That it contains address of instructions
There is a subtle difference between normal (object) pointers and function pointers. It is not possible to access the single instructions of a function - they do not have the same length.
With other pointers the increment (arithmetic) is adapted to the type, whether as p[i] or p + i or *(p+i).
Side note: there still is int at the bottom of the call chain:
return (*(int*)a == *(int*)b);

how does the in-place calculation take place in C

I am working on a simple in-place fourier transform. But I do not know how does the in-place take place. For example the following code snippet, taken from https://rosettacode.org/wiki/Fast_Fourier_transform#C
As the function declares void fft(cplx buf[], int n), without any output, how could the change in buf in the sub-function transfer back into the main function?
#include <stdio.h>
#include <math.h>
#include <complex.h>
double PI;
typedef double complex cplx;
void _fft(cplx buf[], cplx out[], int n, int step)
{
if (step < n) {
_fft(out, buf, n, step * 2);
_fft(out + step, buf + step, n, step * 2);
for (int i = 0; i < n; i += 2 * step) {
cplx t = cexp(-I * PI * i / n) * out[i + step];
buf[i / 2] = out[i] + t;
buf[(i + n)/2] = out[i] - t;
}
}
}
void fft(cplx buf[], int n)
{
cplx out[n];
for (int i = 0; i < n; i++) out[i] = buf[i];
_fft(buf, out, n, 1);
}
void show(const char * s, cplx buf[]) {
printf("%s", s);
for (int i = 0; i < 8; i++)
if (!cimag(buf[i]))
printf("%g ", creal(buf[i]));
else
printf("(%g, %g) ", creal(buf[i]), cimag(buf[i]));
}
int main()
{
PI = atan2(1, 1) * 4;
cplx buf[] = {1, 1, 1, 1, 0, 0, 0, 0};
show("Data: ", buf);
fft(buf, 8);
show("\nFFT : ", buf);
return 0;
}
I am not sure whether I have made the question clear. I wrote a snippet below, with just the same structure with the one above. However, it does not work in in-place mode, by which I mean, the value changes of variable in the sub-function did not transfer into the main function.
#include <stdio.h>
void _sumab(int a, int b, int c)
{
printf("2: %d, %d, %d\n", a, b, c );
a = 2*a + b+c;
b = 12;
// if(a<800) _sumab(a, b, c);
printf("3: %d, %d, %d\n", a, b, c );
}
void sumab(int a, int b, int c)
{
printf("1: %d, %d, %d\n", a, b, c );
_sumab(a, b, c);
a = a*4;
printf("4: %d, %d, %d\n", a, b, c);
}
int main()
{
int out1 = 0;
int out2 = 1;
int out3 = 2;
sumab(out1+100, out2, out3);
printf("5: %d, %d, %d\n", out1, out2, out3);
return 0;
}
in the former code, after calling the sub-function, the value stored in buf changes, even in the main function. but in the latter code, after calling the sub-function, the values of a, b, c remain the same, as they are in the main function scope. Why?
Did I left some important issue or something else? How does the in-place take place?
and if fft(buf, 8) means calculate the fourier transform of buf and store it still in buf, how about the expression fft(buf+2, 8), it will calculate the fourier transform of buf+2, but stores in where?
Thanks in advance.
The key to your question is that in C, you can't pass an array to a function.
When you write this:
void fft(cplx buf[], int n)
The types in that declaration are adjusted * according to the rules defined in §6.7.6.3 p7 of the C11 standard (citing the latest public draft, n1570, here):
A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to
type’’, where the type qualifiers (if any) are those specified within the [ and ] of the
array type derivation. [...]
This means, the real declaration looks like this:
void fft(cplx *buf, int n)
So, you're actually passing a pointer and the function can manipulate the original array through that pointer.
*) It's often said the array decays as a pointer. This is not the official wording of the standard, but widely understood. If you have an array like this:
char a[5];
and you just write a, this is evaluated as a pointer to the first element of a, of type char *. So, with a function declared like this:
void foo(char x[]);
you can just call it like
foo(a);
and what really gets passed is the pointer to the first element of a, therefore, a "decays" as a pointer.

Small generic programming issue in C

So I'm starting to understand the basics of generic programming in C. I'm currently building a program that says if a value occurs or not in a given sequence of number.
I think that the bug occurs in the cmpValues function. Would anyone point it out? (for example, for want=4 and v={1,2,3,4,5}, the program says that want is not in v)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void *search(const void *x, const void *t, int n, int d, int (*cmpValues)(const void *, const void *)){
char *p = (char *)t;
int i;
for(i=0;i<n;++i)
if(cmpValues(x,p+i*d))
return p+i*d;
return NULL;
}
int cmpValues(const void *a, const void *b){
if((char *)a == (char *)b)
return 1;
return 0;
}
int main() {
FILE *f = fopen("datein.txt", "r");
FILE *g = fopen("dateout.txt", "w");
int *v, n, i, want;
fscanf(f, "%d", &n);
v = (int *)malloc(n * sizeof(int));
for(i = 0; i < n; ++i)
fscanf(f, "%d", v + i);
fscanf(f, "%d", &want);
if(search(&want, v, n, sizeof(int), cmpValues))
fprintf(g, "The value %d is found at position %d.\n\n", want, search(&want, v, n, sizeof(int), cmpValues));
else
fprintf(g, "The value does bot occur in the given sequence.\n\n");
return 0;
}
In cmpValues, you are comparing 2 objects pointed by 2 void pointers (i.e. you don't know their type, nor their size). Let's assume we are having ints, and that an int has 4 bytes, which is usually the case.
Just for the sake of it, let's assume that the a pointer has value 0x100 (i.e. points to a int from 0x100 to 0x103, inclusive) and b pointer has a value of 0x104 (i.e. points to the int from 0x104 to 0x107).
Now, you are converting them to char* (char has 1 byte) and compare the value of the pointers. Now, the type of the pointer does not matter in comparisons. In that comparison, you will compare memory addresses (in my example, 0x100 and 0x104). Obviously, the only way the function will return 1 is if the pointers would point to the same variable.
Now, in order to fix it, you should compare the values at the memory addresses pointed by your pointers. However, simply dereferencing the pointers:
*((char *)a) == *((char *)b)
won't be enough, since this would compare just the first byte of a with the first byte of b (under the assumption that char has 1 byte). Also, you can't dereference void*.
So, you need to iterate over your variables and compare them byte by byte (this assumes that you know the size of the data type):
int comp(void *a, void *b, int size) {
// convert a and b to char* (1 byte data type)
char *ca = a;
char *cb = b;
// iterate over size bytes and try to find a difference
for (int i = 0; i < size; i++) {
if (*(ca + i) != *(cb + j)) {
return 0;
}
}
// if no difference has been found, the elements are equal
return 1;
}
side note: you don't need to call cauta twice in main.

Resources