0

I'm trying to feed data into an array and change only a few values and leaving the rest 0, but I keep receiving much more data than the array should theoretically hold. Here is my code compiled and run with

gcc -o arr arrayconst.c

#include <stdio.h>
#include <stdint.h>
int main(){    
    uint16_t buf_tx[101];
    for(int i = 0; i < sizeof(buf_tx);i++){buf_tx[i]=0;}
    //memset(buf_tx,0,sizeof(buf_tx)*sizeof(uint16_t)); //alternate way of zeroizing
    buf_tx[42] = 0x2000;
    buf_tx[46] = 0x2000;
    buf_tx[48] = 0x2000;
    buf_tx[50] = 0x2000;
    buf_tx[52] = 0x2000;
    buf_tx[54] = 0x2000;
    buf_tx[72] = 0x1000;
    buf_tx[76] = 0x0001;
    for(int i = 0; i < sizeof(buf_tx); i++){
        printf("|%d 0x%04X, ",i,buf_tx[i]);
        
    }
}

and my output:

|0 0x0000, |1 0x0000, |2 0x0000, |3 0x0000, |4 0x0000, |5 0x0000, |6 0x0000, |7 0x0000, |8 0x0000, |9 0x0000, |10 0x0000, |11 0x0000, |12 0x0000, |13 0x0000, |14 0x0000, |15 0x0000, |16 0x0000, |17 0x0000, |18 0x0000, |19 0x0000, |20 0x0000, |21 0x0000, |22 0x0000, |23 0x0000, |24 0x0000, |25 0x0000, |26 0x0000, |27 0x0000, |28 0x0000, |29 0x0000, |30 0x0000, |31 0x0000, |32 0x0000, |33 0x0000, |34 0x0000, |35 0x0000, |36 0x0000, |37 0x0000, |38 0x0000, |39 0x0000, |40 0x0000, |41 0x0000, |42 0x2000, |43 0x0000, |44 0x0000, |45 0x0000, |46 0x2000, |47 0x0000, |48 0x2000, |49 0x0000, |50 0x2000, |51 0x0000, |52 0x2000, |53 0x0000, |54 0x2000, |55 0x0000, |56 0x0000, |57 0x0000, |58 0x0000, |59 0x0000, |60 0x0000, |61 0x0000, |62 0x0000, |63 0x0000, |64 0x0000, |65 0x0000, |66 0x0000, |67 0x0000, |68 0x0000, |69 0x0000, |70 0x0000, |71 0x0000, |72 0x1000, |73 0x0000, |74 0x0000, |75 0x0000, |76 0x0001, |77 0x0000, |78 0x0000, |79 0x0000, |80 0x0000, |81 0x0000, |82 0x0000, |83 0x0000, |84 0x0000, |85 0x0000, |86 0x0000, |87 0x0000, |88 0x0000, |89 0x0000, |90 0x0000, |91 0x0000, |92 0x0000, |93 0x0000, |94 0x0000, |95 0x0000, |96 0x0000, |97 0x0000, |98 0x0000, |99 0x0000, |100 0x0000, |101 0x0000, |102 0x0000, |103 0x0000, |104 0x0000, |105 0x0000, |106 0x0000, |107 0x0000, |108 0x0000, |109 0x0000, |110 0x0000, |111 0x0000, |112 0x0000, |113 0x0000, |114 0x0000, |115 0x0000, |116 0x0000, |117 0x0000, |118 0x0000, |119 0x0000, |120 0x0000, |121 0x0000, |122 0x0000, |123 0x0000, |124 0x0000, |125 0x0000, |126 0x0000, |127 0x0000, |128 0x0000, |129 0x0000, |130 0x0000, |131 0x0000, |132 0x0000, |133 0x0000, |134 0x0000, |135 0x0000, |136 0x0000, |137 0x0000, |138 0x0000, |139 0x0000, |140 0x0000, |141 0x0000, |142 0x0000, |143 0x0000, |144 0x0000, |145 0x0000, |146 0x0000, |147 0x0000, |148 0x0000, |149 0x0000, |150 0x0000, |151 0x0000, |152 0x0000, |153 0x0000, |154 0x0000, |155 0x0000, |156 0x0000, |157 0x0000, |158 0x0000, |159 0x0000, |160 0x0000, |161 0x0000, |162 0x0000, |163 0x0000, |164 0x0000, |165 0x0000, *** stack smashing detected ***: terminated Aborted (core dumped)

any help would be greatly appreciated!

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
rob ell
  • 45
  • 7
  • 1
    `sizeof(buf_tx)` is the size in *bytes*. But your array is of 2-byte elements. And your loop really doesn't care about what was initialized and what was not. – Eugene Sh. Nov 03 '20 at 20:57
  • `sizeof(buf_tx)/sizeof(buf_tx[0])` to get elements instead of bytes. – Retired Ninja Nov 03 '20 at 20:57

2 Answers2

0

sizeof gives the number of bytes in its operand. In typical C implementations, uint16_t is two bytes, so uint16_t buf_tx[101] is 202 bytes.

To get the number of elements in an array x, use sizeof x / sizeof *x:

for (int i = 0; i < sizeof buf_tx / sizeof *buf_tx; i++)

This is often packaged in a macro:

#define NumberOf(x) (sizeof (x) / sizeof *(x))
…
for (int i = 0; i < NumberOf(buf_tx); i++)

This works only for arrays, not for pointers, because sizeof x gives the size of the array if x is an array but the size of the pointer if x is a pointer. Notably, function parameters declared as arrays, such as void foo(int x[]), are automatically adjusted to be pointers, so NumberOf(x) will not work for them.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • "In typical C implementations, uint16_t is two bytes", in which implementation is uint16_t not 2 bytes? – Stefan Riedel Nov 03 '20 at 21:30
  • @StefanRiedel: In a C implementation in which `unsigned char` is 16 bits. [See here.](https://stackoverflow.com/questions/5516044/system-where-1-byte-8-bit) The C standard only requires that character types such as `char` be at least 8 bits (by bounds it places on `UCHAR_MAX` and such), not that they be only 8 bits. In the C standard, “byte” is the size of the character types. So, in a C implementation with 16-bit characters, a byte would be 16 bits. – Eric Postpischil Nov 03 '20 at 21:40
0

If you have an array array then the number of elements in the array is determinate by this expression

sizeof( array ) / sizeof( *array )

So in the loops you need to use this expression.

It is better to define a corresponding constant like

const size_t N = sizeof( buf_tx ) / sizeof( *buf_tx );

and use it in loops like

for ( size_t i = 0; i < N; i++ ) buf_tx[i] = 0; 

Or

for ( size_t i = 0; i < N; i++ )
{
    printf("|%zu %#06x, ",i,buf_tx[i] );
}

Pay attention to that for objects of the type size_t you need to use the conversion specifier %zu. And instead of writing manually 0x before the conversion specifier for outputted number you could use the flag # as %#06x.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335