0

I got this kind of problem with using uint8_t as array which is passed to my transferring function. At the moment of passing from main function to transfer it changes size to 4 elements. Same thing with array which I create inside my transfer function, even though I manually create another array to send my values with passed length from main function. I understand it is because of data alignment and padding on my processor. Is there any way to solve it? Or I'm printing it wrong.

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

#define ARRAY_SIZE(a)  (sizeof(a) / sizeof(uint8_t))

static const char *device = "/dev/spidev0.0";
static uint8_t mode;
static uint8_t bits = 8;
static uint32_t speed = 1000000;
static uint16_t delay;


static void transfer(int fd, const uint8_t *pass, size_t arsize)
{
int ret,i,k;
printf(" rozmiar tabpass=%d ", arsize);
uint8_t *rx = (uint8_t*) malloc(arsize * sizeof(uint8_t)); 
//this is where I create rx with arsize lenght
uint8_t *tx = (uint8_t*) malloc(arsize * sizeof(uint8_t));
for (i = 0; i < arsize; i++){
    *(rx + i) = 0;
    *(tx + i) = *(pass + i);
}
for (k = 0; k < (sizeof (pass) / sizeof (pass[0])); k++) {
    printf(" a%X\n ", pass[k]); 
//here I check length of passed array
}
for (k = 0; k < (sizeof (tx) / sizeof (tx[0])); k++) {
    printf(" b%X\n ", tx[k]); 
// I check length of newly created array, should be equal to array size
}
printf(" rozmiar tabtx=%d ", ARRAY_SIZE(tx));
struct spi_ioc_transfer tr = {
    .tx_buf = (unsigned long)tx,
    .rx_buf = (unsigned long)rx,
    .len = arsize,
    .delay_usecs = delay,
    .speed_hz = speed,
    .bits_per_word = bits,
    .cs_change = 0,
};

ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
printf(" rozmiar tabrx=%d ", ARRAY_SIZE(rx)); 
//here it prints size of array equals 4
for (ret = 0; ret < arsize; ret++) {
    if (!(ret % 6))
        puts("");

    printf("%d. %.2X ", ret, rx[ret]);

}
puts("");
tr.cs_change = 1;
}

int main(int argc, char *argv[])
{
int ret = 0;
int fd;

fd = open(device, O_RDWR);

/*
* spi mode
*/
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);

ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);

/*
* bits per word
*/
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);

ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);

/*
* max speed hz
*/
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);

ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);

printf("spi mode: %d\n", mode);
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed / 1000);

uint8_t tx1[] = {
    0x0, 0x1b, 0xa5
};
transfer(fd, tx1, ARRAY_SIZE(tx1));

uint8_t tx2[] = {
    0x0, 0x33, 0x30
};
printf(" %d. ", ARRAY_SIZE(tx2));
transfer(fd, tx2, ARRAY_SIZE(tx2));

uint8_t tx3[] = {
    0x0, 0x52, 0x90
};
transfer(fd, tx3, ARRAY_SIZE(tx3));

uint8_t tx4[] = {
    0x80, 0x60
};
printf(" %d. ", ARRAY_SIZE(tx4));
transfer(fd, tx4, ARRAY_SIZE(tx4));

close(fd);

return ret;
}
Cœur
  • 37,241
  • 25
  • 195
  • 267

1 Answers1

1

For the sizeof operator to give the actual size of the array, you need to:

  1. Allocate the array statically
  2. Refer to the array within its scope of declaration

For example:

void func()
{
    int arr[10];
    int total_size = sizeof(arr);
    int num_of_elements = sizeof(arr)/sizeof(*arr);
    ...
}

An example of when the array is not statically allocated:

void func()
{
    int* arr = malloc(sizeof(int)*10);
    int total_size = sizeof(arr); // will give you the size of 'int*'
    ...
}

An example of when the array is not within its scope of declaration:

void func(int arr[]) // same as 'int* arr'
{
    int total_size = sizeof(arr); // will give you the size of 'int*'
    ...
}
barak manos
  • 29,648
  • 10
  • 62
  • 114
  • 1
    I would add that for nearly all practical purposes, an array as a function parameter is an alternate syntax to calling it a pointer. This post explains the one difference: http://stackoverflow.com/questions/5573310/difference-between-passing-array-and-array-pointer-into-function-in-c – Brian McFarland Jan 23 '15 at 19:22
  • @BrianMcFarland: Yep, I should probably add that an array decays to a pointer when passed to a function. – barak manos Jan 23 '15 at 19:25
  • Ok, that's why I tried to create my own array tx to refer to within a scope of declaration. And it doesn't explain why array rx is 4 elements long when my arsize only takes 2 or 3 as values, its size is printed within transfer function. – Julian Modlinski Jan 23 '15 at 19:39
  • @BrianMcFarland: They're identical as far as the language standard is concerned. A function declaration like `void func(int arr[])`, or even `void func(int arr[42])`, actually *means* `void func(int *arr)` – Keith Thompson Jan 23 '15 at 19:48
  • @Eggboard: You seem to have missed the part where I mention that the `sizeof` operator gives you the actual size of the array only when it is **statically-allocated**. And as I've shown in the second example above - your `rx` array is **NOT** statically allocated. – barak manos Jan 23 '15 at 20:06
  • You are totally right I should read sizeof doc more carefully. – Julian Modlinski Jan 23 '15 at 20:36
  • @KeithThompson - See the link for the ONE way an array as a function argument can be different, in C99-only. Although AFAIK not many compilers enforce this. Here's [another discussion](http://stackoverflow.com/questions/3430315/purpose-of-static-keyword-in-array-parameter-of-function) on the same feature. – Brian McFarland Jan 23 '15 at 20:39
  • @BrianMcFarland: Ok, you're right -- but it applies only when the keyword `static` is added. Note that for `void func(int arr[static 10])`, the standard says that the argument "shall" provide access to the first element of an array of a least 10 elements (N1570 6.7.6.3p7). Since the word "shall" is not in a constraint, it means that violating it causes undefined behavior; a compiler isn't required to enforce it (and it's not always possible to do so). It permits the compiler to optimize based on the *assumption* that there's an array of at least 10 elements. – Keith Thompson Jan 23 '15 at 20:46