len of array always 2 - c

int *a[4] = {
(int[]){ 1},
(int[]){ -4, -5},
(int[]){ -4, -5, 0},
(int[]){ 1, 3, 4, 6}
};
for (i = 0; i < 4; i++)
len = sizeof(a[i])/sizeof(int);
I know it is not a correct approach, but len is always 2. Could someone explain why len is two? Is it a undefined behavior, if not, how is it being calculated?

a[i] is pointer to int. sizeof(a[i]) will return sizeof int *, not the array it points to. On 64-bit machines, size of a pointer is 8 bytes and size of int is 4 bytes. 8/4 = 2.

Related

Need Help Finding Segmentation fault in C Program

I'm implementing the Data Encryption Standard in C for a personal learning project and I have a seg fault that has been driving me up the wall for the past 3 days. I understand this isn't the place for "fix my code for me" type questions, but I need a second pair of eyes to look over this:
/*we must define our own modulo, as the C modulo returns unexpected results:*/
#define MOD(x, n) ((x % n + n) % n)
/*example: the 12th bit should be in the second byte so return 1 (the first byte being 0)*/
#define GET_BYTE_NUM(bit_index) (bit_index/8)
/*example: a bit index of 12 means this bit is the 4th bit of the second byte so return 4*/
#define GET_BIT_NUM(bit_index) MOD(bit_index, 8)
typedef unsigned char byte;
/*each row represents a byte, at the bit to be place in the position
* for example for the first row (first byte) we will place bits 31, 0, 1, 2, 3, 4 in
* in bit positions 0-6, respectively. The last two bits will be left blank. Since this is supposed to be a crypto implementation, static prevents this value from being accessed outside the file.*/
const static byte e_box[8][6] = { {31, 0, 1, 2, 3, 4}, {3, 4, 5, 6, 7, 8}, {7, 8, 9, 10, 11, 12}, {11, 12, 13, 14, 15, 16}, {12, 16, 17, 18, 19, 20}, {19, 20, 21, 22, 23, 24},
{23, 24, 25, 26, 27, 28}, {27, 28, 29, 30, 31, 0} }
void e(byte **four_byte_block)
{
int i, n, l = 0, four_bit_num, four_byte_num;
/*create the new byte_block and initialize all values to 0, we will have 4 spaces of bytes, so 32 bits in total*/
byte *new_byte_block = (byte*)calloc(4, sizeof(byte));
byte bit;
for(i = 0 i < 8; i++)
{
for(n = 0; n < 6; n++)
{
/*get the byte number of the bit at l*/
four_byte_num = GET_BYTE_NUM(e_box[i][n]);
/*find what index the bit at l is in its byte*/
half_bit_num = GET_BIT_NUM(e_box[i][n]);
bit = *four_byte_block[half_byte_num]; /*SEG FAULT!*/
}
}
/*finally, set four_byte_block equal to new_byte_block*/
/*four_byte_block = NULL;
* four_byte_block = new_byte_block;*/
}
I have narrowed the problem down to the line marked /SEG FAULT!/ but I can't see what the issue is. When I print the half_byte_num, I get a number that is within bounds of half_block, and when I print the values of half_block, I can confirm that those values exist.
I believe I may be doing something wrong with the pointers ie by passing **four_byte_block, (a pointer to a pointer) and it's manipulation could be causing the seg fault.
Have you tried this:
bit = (*four_byte_block)[half_byte_num];
Instead of this:
bit = *four_byte_block[half_byte_num];
Those are not the same, as an example, take the following code:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
char **lines = malloc(sizeof(char *) * 8);
for (int i = 0; i < 8l; i++)
lines[i] = strdup("hey");
printf("%c\n", *lines[1]);
printf("%c\n",(*lines)[1]);
return 0;
}
The former will output h.
The latter will output e.
This is because of the operators precedence, [] will be evalued before *, thus if you want to go to the nth index of *foo, you need to type (*foo)[n].

What does prevent a compiler from deducing the size of column? [duplicate]

This question already has answers here:
Why is char[][] = {{...}, {...}} not possible if explicitly given a multidimensional array?
(5 answers)
Array type has incomplete element type error in C [duplicate]
(1 answer)
Closed 1 year ago.
Why do we need the column size for
int arr[][] = { {1,2,3},{1,3,5} };//int arr[][3]
In this particular example, why can't the compiler deduce it from the data that it has to pack only 3 elements each into each row? Why is there a limitation on compiler for doing it?
I can understand if it was
int arr[][] = { 1,2,3,1,3,5 };
then the compiler has no information of how much data has to be packed into each row.
I read a similar question Why do we need to specify the column size when passing a 2D array as a parameter?. But it doesn't contain the answer.
Edit: To avoid confusion, I am talking about the exact format of data mentioned above.
What does prevent a compiler from deducing the size of column?
The C standard.
From the standard:
6.7.9 Initialization
The type of the entity to be initialized shall be an array of unknown size or a complete object type that is not a variable length array type.
So you can initialize "an array of unknown size" but you can't initialize "an array of unknown size of array of unknown size".
Because you may want the array size to be greater than it is deduced. Like
int arr[5] = {1, 2, 3}; // Last two elements are zero.
If you declare the array like
int arr[][] = { {1, 2, 3}, {1, 3, 5, 7} };
What should the compiler do, report the error, since it expects the array int array[][3], or make the array int array[][4]? This decision is left to be up to a human.
The 2-D arrays are flat in the memory. For example int arr[3][3] and int arr[9] have the same storage. Thus, it is allowed to initialize both vectors by one initializing lists, it can be considered as placing initializing list values directly to a flat memory:
#include <stdio.h>
#include <memory.h>
int main(void) {
int arr2d[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
int arr1d[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
printf("size: %d\n", sizeof(arr2d) == sizeof(arr1d));
printf("memcmp: %d\n", memcmp(arr2d, arr1d, sizeof(arr2d)));
return 0;
}
// size: 1
// memcmp: 0
Extending the above, all 4 functions bellow declare and initialize the same array int arr[3][3] differently:
#include <stdio.h>
void arr2_list2(void) {
int arr[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
printf("int arr[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}:\n");
for (int i = 0; i < 3; ++i)
printf("%d %d %d\n", arr[i][0], arr[i][1], arr[i][2]);
return 0;
}
void arr2_list1(void) {
int arr[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
printf("int arr[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8}:\n");
for (int i = 0; i < 3; ++i)
printf("%d %d %d\n", arr[i][0], arr[i][1], arr[i][2]);
return 0;
}
void arr2open_list2(void) {
int arr[][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
printf("int arr[][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}:\n");
for (int i = 0; i < 3; ++i)
printf("%d %d %d\n", arr[i][0], arr[i][1], arr[i][2]);
return 0;
}
void arr2open_list1(void) {
int arr[][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
printf("int arr[][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8}:\n");
for (int i = 0; i < 3; ++i)
printf("%d %d %d\n", arr[i][0], arr[i][1], arr[i][2]);
return 0;
}
int main(void) {
arr2_list2();
arr2_list1();
arr2open_list2();
arr2open_list1();
return 0;
}
// int arr[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}:
// 0 1 2
// 3 4 5
// 6 7 8
// int arr[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8}:
// 0 1 2
// 3 4 5
// 6 7 8
// int arr[][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}:
// 0 1 2
// 3 4 5
// 6 7 8
// int arr[][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8}:
// 0 1 2
// 3 4 5
// 6 7 8
Imaging int arr[][] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}; is allowed, why would not int arr[][] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; be allowed then, but how can the compiler decide what a human means in the statement
int arr[][] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
int arr[1][9], or int arr[3][3], or int arr[9][1]?
Simple answer - in a declaration like
int arr[][] = { ... };
the element type is int [], which is an incomplete type, and you cannot declare an array where the element type is incomplete. The presence or absence of an initializer doesn’t change that. All an initializer can tell you is how many elements you have of the given element type; it can’t tell you what that element type is.
By contrast, in the declaration
int arr[] = { ... };
the element type is int, which is a complete type. You still need something in the initializer to determine the number of elements, but it’s not telling you how big each element needs to be.
That's because although the [][] syntax looks like array-of-arrays, in memory it is laid like 1-D array. If we imagine a 3x3 chessboard it would be laid out as {1A, 2A, 3A, 1B, 2B, 3B, 1C, 2C, 3C}. The only way to access it as 2-D is to address it as [row + column * columnsize].
Now it's clear that you MUST know the columnsize in order to even start thinking about accessing the elements of the array. Where is this columnsize parameter stored? The array is of type int (*)[3]. Columnsize is an integral part of the type as much as "t" is a part of int.
What are you asking for is auto type. The compiler would have to determine the entire type on its own. It's equivalent of wanting auto arr = 1; or auto arr = "foo";. C compiler doesn't deal in such tricks.
Notice that columnsize is entirely different creature than the length of an array. int arr[] = {1} is of exactly same type as int arr[] = {1,2,3} The compiler couldn't care less about the length (actual size in memory) of the array, not going out of bounds is entirely your responsibility. That's why one element could be left unspecified. Not because the compiler can figure it out, but because the compiler ignores it.
int arr[][2] = {1,2,3,4,5,6} is of entirely different type than int arr[][3] = {1,2,3,4,5,6}, even though they're same size in memory. To the compiler, they're like int[1] and char[4].
The {{},{}} is just a syntactic sugar to help YOU, not the compiler.

C - delete element from array and reorganise

Given this array:
int a[] = {5, 8, 5, 6, 9, 5};
Would it be possible to remove all ints which equals 5 and move the rest the front of the array?
So that after the removal the array would look like this:
int a[] = {8, 6, 9, 0, 0, 0}
I don't know if by removing a element it becomes a 0 or a NULL?
Thanks!
You can do it with two iterations over the array, first iteration two to turn the element you want to delete, second iteration to separate zeros from non-zeros.
int a[] = {5, 8, 5, 6, 9, 5};
int n = 6;
for(int i = 0 ; i < n ; i++ ) {
if(a[i] == 5 ) {
a[i] = 0;
}
}
int* zero = a;
int* nonZero = a;
int j = 0;
while(j < n) {
while(*zero != 0) {
zero++;
}
while(*nonZero == 0) {
nonZero++;
j++;
}
if(zero < nonZero) {
*zero = *nonZero;
*nonZero = 0;
}
j++;
}
Your array is statically allocated, so always has the same size and deleted elements have the 0 value (according how you define the deleted values).
This link can help you and explains about how to delete element from array.
It is been awhile that i have programmed in C but it is posibble.
This is just a pseudo code, but you just need to change it to way of C programming.
int a[] = {5, 8, 5, 6, 9, 5};
int b[] = {5, 8, 5, 6, 9, 5}; // copy of array a to hold temp
for(int i = 0; i < Size of array; i++ ){
for(int j = i; j < Size of array; j++ ){
if(b[j] != 5){
a[i] = b[j];
a[j] = b[i];
break;
}
}
}
It will be like (▼: Target to swap, F: Finished, X: Not a targe to swap, N: Not processed):
▼, ▼, N, N, N, N
5, 8, 5, 6, 9, 5
F, ▼, X, ▼, N, N
8, 5, 5, 6, 9, 5
F, F, ▼, X, ▼, N
8, 6, 5, 5, 9, 5
Result:
8, 6, 9, 5, 5, 5
And remove 5s, it is quite different depends what you mean. If you do not change size of array then they can be 0 or undefined(null). So I think it differs by how you program the function that returns array.
your array is not dynamic so you just can't reduce its size after its been allocated.setting the value zero might solve the problem in your case.

How to initialize only few elements of an array with some values?

Is it possible to assign some values to an array instead of all? To clarify what I want:
If I need an array like {1,0,0,0,2,0,0,0,3,0,0,0} I can create it like:
int array[] = {1,0,0,0,2,0,0,0,3,0,0,0};
Most values of this array are '0'. Is it possible to skip this values and only assign the values 1, 2 and 3? I think of something like:
int array[12] = {0: 1, 4: 2, 8: 3};
Is it possible to skip this values and only assign the values 1, 2 and 3?
In C, Yes. Use designated initializer (added in C99 and not supported in C++).
int array[12] = {[0] = 1, [4] = 2, [8] = 3};
Above initializer will initialize element 0, 4 and 8 of array array with values 1, 2 and 3 respectively. Rest elements will be initialized with 0. This will be equivalent to
int array[12] = {1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0};
The best part is that the order in which elements are listed doesn't matter. One can also write like
int array[12] = {[8] = 3, [0] = 1, [4] = 2};
But note that the expression inside [ ] shall be an integer constant expression.
Here is my trivial approach:
int array[12] = {0};
array[0] = 1; array[4] = 2; array[8] = 3;
However, technically speaking, this is not "initializing" the array :)
An alternative way to do it would be to give default value by memset for all elements in the array, and then assign the specific elements:
int array[12];
memset(array, 0, sizeof(int) * 12); //if the default value is 0, this may not be needed
array[0] = 1; array[4] = 2; array[8] = 3;
Standard C17
The standard (C17, N2176) has an interesting example in § 6.7.9(37):
EXAMPLE 13 Space can be “allocated” from both ends of an array by using a single designator:
int a[MAX] = {
1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0
};
In the above, if MAX is greater than ten, there will be some
zero-valued elements in the middle; if it is less than ten, some of
the values provided by the first five initializers will be overridden
by the second five.
Example
#include <stdio.h>
#define MAX 12
int main(void)
{
// n2176, § 6.7.9(37)
int a[MAX] = {
1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0
};
for (size_t i = 0; i < MAX; i++) {
printf("%d\n", a[i]);
}
return 0;
}
Output:
1
3
5
7
9
0 <-- middle element, defaults to zero
0 <-- middle element, defaults to zero
8
6
4
2
0

Converting to ASCII in C

Using a microcontroller (PIC18F4580), I need to collect data and send it to an SD card for later analysis. The data it collects will have values between 0 and 1023, or 0x0 and 0x3FF.
So what I need to do is convert 1023 into a base 10 string of literal ASCII values (0x31, 0x30, 0x32, 0x33, ...).
My problem is that the only way I can think of to split the digits apart requires a lot of division.
char temp[4];
temp[0] = 1023 % 10;
temp[1] = (1023 % 100) / 10;
temp[2] = (1023 % 1000) / 100;
temp[3] = (1023 % 10000) / 1000;
Using this method, finding the ASCII values of an n digit decimal number requires 2n-1 divisions. Is there a method that would be faster?
The end goal of this is to wind up with a .csv file on the SD card that can quickly be plugged into any laptop to see a graph of the data in Excel.
The obvious solution is not to convert the data to ASCII at all but store it in binary format. That way all you need to worry about is the endianness of the data. If the system performing the later analysis is far more powerful than your embedded target, then it would make sense to let that deal with the conversion and and byte order.
On the other hand, it is possible that the execution time of the / and % is insignificant compared to the time taken to transfer the data to the SD card; so make sure that you are optimising the right thing.
There's certainly a much faster way: have an array of 1024 pre-computed strings. Then you can just do bounds checking, followed by an index into the array.
It's unclear from your question whether your code is running on the microcontroller though. If that's the case, you may not have enough memory for this approach.
I agree with what Clifford said, that you shouldn't worry about optimizing it if you don't have to, and that you can push the log cleanup to your analysis platform, rather than worrying about formatting in an embedded application.
That being said, here's an article that might be useful to you. It uses a loop, shifts, additions and branches, with linear/constant complexity: http://www.johnloomis.org/ece314/notes/devices/binary_to_BCD/bin_to_bcd.html
Also, I thought it would be fun to make some code that doesn't perform any divides, multiplies, or branches, but still gives the correct answer [0 - 1024). No promises that this is any faster than other options. This sort of code is just an option to explore.
I'd love to see if anyone can provide some tricks to make the code smaller, require less memory, or require fewer operations, while keeping the rest of the counts equal, or shrinking them :)
Stats:
224 bytes in constants (no idea on the code size)
5 bit-shift-rights
3 subtracts
5 bitwise-ands
4 bitwise-ors
1 greater-than comparison
Perf:
Using the perf comparisons and itoa routines in Jonathan Leffler's answer, here are the stats I got:
Division 2.15
Subtraction 4.87
My solution 1.56
Brute force lookup 0.36
I increased the iteration count to 200000 to ensure I didn't have any problems with timing resolution, and had to add volatile to the function signatures so that the compiler didn't optimize out the loop. I used VS2010 express w/ vanilla "release" settings, on a 3ghz dual core 64 bit Windows 7 machine (tho it compiled to 32 bit).
The code:
#include "stdlib.h"
#include "stdio.h"
#include "assert.h"
void itoa_ten_bits(int n, char s[])
{
static const short thousands_digit_subtract_map[2] =
{
0, 1000,
};
static const char hundreds_digit_map[128] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
0, 0, 0,
};
static const short hundreds_digit_subtract_map[10] =
{
0, 100, 200, 300, 400, 500, 600, 700, 800, 900,
};
static const char tens_digit_map[12] =
{
0, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9,
};
static const char ones_digit_map[44] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3
};
/* Compiler should optimize out appX constants, % operations, and + operations */
/* If not, use this:
static const char ones_digit_append_map[16] =
{
0, 6, 2, 8, 4, 10, 6, 12, 8, 14, 10, 16, 12, 18, 14, 20,
};
*/
static const char a1 = 0x10 % 10, a2 = 0x20 % 10, a3 = 0x40 % 10, a4 = 0x80 % 10;
static const char ones_digit_append_map[16] =
{
0, a1, a2, a1 + a2,
a3, a1 + a3, a2 + a3, a1 + a2 + a3,
a4, a1 + a4, a2 + a4, a1 + a2 + a4,
a3 + a4, a1 + a3 + a4, a2 + a3 + a4, a1 + a2 + a3 + a4,
};
char thousands_digit, hundreds_digit, tens_digit, ones_digit;
assert(n >= 0 && n < 1024 && "n must be between [0, 1024)");
/* n &= 0x3ff; can use this instead of the assert */
thousands_digit = (n >> 3 & 0x7f) > 0x7c;
n -= thousands_digit_subtract_map[thousands_digit];
ones_digit = ones_digit_map[
(n & 0xf)
+ ones_digit_append_map[n >> 4 & 0xf]
+ ones_digit_append_map[n >> 8 & 0x3]
];
n -= ones_digit;
hundreds_digit = hundreds_digit_map[n >> 3 & 0x7f];
n -= hundreds_digit_subtract_map[hundreds_digit];
tens_digit = tens_digit_map[n >> 3];
s[0] = '0' | thousands_digit;
s[1] = '0' | hundreds_digit;
s[2] = '0' | tens_digit;
s[3] = '0' | ones_digit;
s[4] = '\0';
}
int main(int argc, char* argv)
{
int i;
for(i = 0; i < 1024; ++i)
{
char blah[5];
itoa_ten_bits(i, blah);
if(atoi(blah) != i)
printf("failed %d %s\n", i, blah);
}
}
There's a way of doing it using subtractions, but I am not convinced it's faster than using subtractions and modulus on a "normal" CPU (may be different in an embedded environment).
Something like this:
char makedigit (int *number, int base)
{
static char map[] = "0123456789";
int ix;
for (ix=0; *number >= base; ix++) { *number -= base; }
return map[ix];
}
char *makestring (int number)
{
static char tmp[5];
tmp[0] = makedigit(&number, 1000);
tmp[1] = makedigit(&number, 100);
tmp[2] = makedigit(&number, 10);
tmp[3] = makedigit(&number, 1);
tmp[4] = '\0';
return tmp;
}
Then, a call to makestring() should result in a (static, so copy it before overwriting) string with the converted number (zero-prefixed, at 4 characters width, as the original assumption is a value in the 0-1023 range).
With some care in finding the right number(s) to use, you can multiply by the reciprocal of the base rather than dividing by the base. Terje's code is for an x86, but porting the general idea to a PIC shouldn't be tremendously difficult.
If the values are correctly in range (0..1023), then your last conversion is unnecessarily wasteful on the divisions; the last line could be replaced with:
temp[3] = 1023 / 1000;
or even:
temp[3] = 1023 >= 1000;
Since division is repeated subtraction, but you have a very special case (not a general case) division to deal with, I'd be tempted to compare the timings for the following code with the division version. I note that you put the digits into the string in 'reverse order' - the least significant digit goes in temp[0] and the most in temp[4]. Also, there is no chance of null-terminating the string given the storage. This code uses a table of 8 bytes of static data - considerably less than many of the other solutions.
void convert_to_ascii(int value, char *temp)
{
static const short subtractors[] = { 1000, 100, 10, 1 };
int i;
for (i = 0; i < 4; i++)
{
int n = 0;
while (value >= subtractors[i])
{
n++;
value -= subtractors[i];
}
temp[3-i] = n + '0';
}
}
Performance testing - Intel x86_64 Core 2 Duo 3.06 GHz (MacOS X 10.6.4)
This platform is probably not representative of your microcontroller, but the test shows that on this platform, the subtraction is considerably slower than the division.
void convert_by_division(int value, char *temp)
{
temp[0] = (value % 10) + '0';
temp[1] = (value % 100) / 10 + '0';
temp[2] = (value % 1000) / 100 + '0';
temp[3] = (value % 10000) / 1000 + '0';
}
void convert_by_subtraction(int value, char *temp)
{
static const short subtractors[] = { 1000, 100, 10, 1 };
int i;
for (i = 0; i < 4; i++)
{
int n = 0;
while (value >= subtractors[i])
{
n++;
value -= subtractors[i];
}
temp[3-i] = n + '0';
}
}
#include <stdio.h>
#include <timer.h>
#include <string.h>
static void time_convertor(const char *tag, void (*function)(void))
{
int r;
Clock ck;
char buffer[32];
clk_init(&ck);
clk_start(&ck);
for (r = 0; r < 10000; r++)
(*function)();
clk_stop(&ck);
printf("%s: %12s\n", tag, clk_elapsed_us(&ck, buffer, sizeof(buffer)));
}
static void using_subtraction(void)
{
int i;
for (i = 0; i < 1024; i++)
{
char temp1[4];
convert_by_subtraction(i, temp1);
}
}
static void using_division(void)
{
int i;
for (i = 0; i < 1024; i++)
{
char temp1[4];
convert_by_division(i, temp1);
}
}
int main()
{
int i;
for (i = 0; i < 1024; i++)
{
char temp1[4];
char temp2[4];
convert_by_subtraction(i, temp1);
convert_by_division(i, temp2);
if (memcmp(temp1, temp2, 4) != 0)
printf("!!DIFFERENCE!! ");
printf("%4d: %.4s %.4s\n", i, temp1, temp2);
}
time_convertor("Using division ", using_division);
time_convertor("Using subtraction", using_subtraction);
time_convertor("Using division ", using_division);
time_convertor("Using subtraction", using_subtraction);
time_convertor("Using division ", using_division);
time_convertor("Using subtraction", using_subtraction);
time_convertor("Using division ", using_division);
time_convertor("Using subtraction", using_subtraction);
return 0;
}
Compiling with GCC 4.5.1, and working in 32-bit, the average timings were (optimization '-O'):
0.13 seconds using division
0.65 seconds using subtraction
Compiling and working in 64-bit, the average timings were:
0.13 seconds using division
0.48 seconds using subtraction
Clearly, on this machine, using subtraction is not a winning proposition. You would have to measure on your machine to make a decision. And removing the modulo 10000 operation will only skew results in favour of the division (it knocks about 0.02 seconds off the time with division when replaced with the comparison; that's a 15% saving and worth having).
Is there some reason that you're particularly concerned about this?
If your compiler and C library provide an itoa() function, use that, and then worry about writing this code (and associated tests and so forth to make sure you got it right!) if for some reason that turns out to be too slow or doesn't fit into RAM or something.
I've replaced my previous answer with a better one. This code creates a 4-character string in the proper order, most significant digit in output[0] to least significant in output[3] with a zero terminator in output[4]. I don't know anything about your PIC controller or C compiler, but this code doesn't require anything more than 16-bit integers, addition/subtraction, and shifting.
int x;
char output[5];
output[4] = 0;
x = 1023;
output[3] = '0' + DivideByTenReturnRemainder(&x);
output[2] = '0' + DivideByTenReturnRemainder(&x);
output[1] = '0' + DivideByTenReturnRemainder(&x);
output[0] = '0' + x;
The key to this is the magical function DivideByTenReturnRemainder. Without using division explicitly it's still possible to divide by powers of 2 by shifting right; the problem is that 10 isn't a power of 2. I've sidestepped that problem by multiplying the value by 25.625 before dividing by 256, letting integer truncation round down to the proper value. Why 25.625? Because it's easily represented by powers of 2. 25.625 = 16 + 8 + 1 + 1/2 + 1/8. Again, multiplying by 1/2 is the same as shifting right one bit, and multiplying by 1/8 is shifting right by 3 bits. To get the remainder, multiply the result by 10 (8+2) and subtract it from the original value.
int DivideByTenReturnRemainder(int * p)
{
/* This code has been tested for an input range of 0 to 1023. */
int x;
x = *p;
*p = ((x << 4) + (x << 3) + x + (x >> 1) + (x >> 3)) >> 8;
return x - ((*p << 3) + (*p << 1));
}
Are you required to use an ASCII string of the decimal representation? It would be much easier to store it in hexadecimal format. No division required, only (relatively cheap) shift operations. Excel should be able to read it if you prepend a '0x' to each number.

Resources