Incorrect result for %p when implementation printf - c

I'm working on my own printf code and I got 2 problems that I hoped you might be able to help me with.
The first one is with the %p option :
This option gives me the pointer address of a void* in hex form.
So what I'm doing is this :
void printp(void *thing)
{
dectohex((long)&thing, 1);
}
where dectohex is just a function converting a decimal to hex.
The result will always be correct, except for the last 3 characters. Always. For example :
me : 0x5903d8b8 , printf : 0x5903da28.
And these characters don't change very often, whereas the other part changes at each call like its supposed to.
The other problem I have is with the %O option. I can't manage to convert a signed int to an unsigned int. printf prints huge numbers for negative int's, and no casts seems to work since I wouldn't have the place to store it anyways.
EDIT:
Thanks sooo much for the answers, so apparently for the first problem i was just a little stupid. For the second question i'm gonna try the different solutions you gave me and update you if i manage to do it.
Again thanks so much for your time and patience, and sorry for the delay in my response, i checked the email alert for any answer but it doesn't work apparently.
REEDIT: After reading your answers to my second question more carefully, i think some of you think i asked about %o or %0. I was really talking about %O as in %lo i think. In the man it tells me "%O : The long int argument is converted to unsigned octal". My problem is before converting the long int to octal, i need to convert it to something unsigned.

If uintptr_t/intmax_t is defined (it is optional), convert the pointer to that integer type and then print.
Otherwise, if sizeof(uintmax_t) >= sizeof (void *) , convert to uintmax_t. uintmax_t is a required type, but may not be sufficiently large.
void printp(void *thing) {
uintptr_t j = (uintptr_t) thing;
char lst[(sizeof j * CHAR_BIT + 3)/ 4 + 1]; // Size needed to print in base 16
char *p = &lst[sizeof lst] - 1;
*p = '\0';
do {
p--;
*p = "0123456789ABCDEF"[j%16];
j /= 16;
} while (p > lst);
fputs(p, stdout);
}
The %O problem is likely a sign extension issue. (#mafso) Insure valuables used are unsigned, like unsigned and unsigned long. Without seeing the code difficult to know for sure.

About the first issue you're having, just to make sure, you want to print the address of thing (note that thing itself is a pointer) or the address of the origin of thing (the pointer to the pointer thing)?
You're currently printing the pointer to the pointer.
Change
dectohex((long)&thing, 1);
to
dectohex((long)thing, 1);
if that is the case.
About the %O problem, can you give a code example?

You need "unsigned long long" for your cast.
Pointers are unsigned, but long is signed.
The number of bits in any data type is implementation-dependent; however these days it is common for long and unsigned long to be 32 bits.
edit: to be more clear, you can't count on anything about the number of bits in C, C++ or Objective-C, it's always implementation-dependent. For example it was at one time common to have nine bit bytes and thirty-six bit words. That's why the Internet Protocols always specify "octets" - groups of eight bites - rather then "bytes".
That's one advantage of Java, in that the number of bits in each data type is strictly definited.

About your second question regarding zero-padding and negative integers, which seems entirely separate from the first question about hex output. You can handle negative numbers like this (although in 32-bit it does not work with the value -2147483648 which is 0x80000000).
#include <stdio.h>
#define MAXDIGITS 21
int printint(int value, int zeropad, int width)
{
int i, z, len = 0;
char strg [MAXDIGITS+1];
strg [MAXDIGITS] = 0;
if (value < 0) {
value = - value;
putchar ('-');
len = 1;
}
for (i=MAXDIGITS-1; i>=0; i--) {
strg [i] = '0' + value % 10;
if ((value /= 10) == 0)
break;
}
if (zeropad)
for (z=MAXDIGITS-i; z<width; z++) {
putchar ('0');
len++;
}
for (; i<MAXDIGITS; i++) {
putchar (strg [i]);
len++;
}
return len;
}
int main (int argc, char *argv[])
{
int num = 0, len;
if (argc > 1) {
sscanf (argv[1], "%d", &num);
// try the equivalent of printf("%4d, num);
len = printint (num, 0, 4);
printf (" length %d\n", len);
// try the equivalent of printf("%04d, num);
len = printint (num, 1, 4);
printf (" length %d\n", len);
}
return 0;
}

Related

6-bit binary counter in C (compiles, but then Windows encounters error) [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am extremely new to C and trying to make a 6-bit binary counter, where each return has all 6 digits listed (i.e 000000, 000001,...). Currently, my solution compiles but does not execute once compiled (I get a warning that says something to the effect of "A problem caused Windows to stop working" and then no output is displayed). If anyone could help figure out why this happens, or suggest a better way to do this since I know my approach is extremely convoluted, I'd appreciate the help!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
long * convert(long dec){
if(dec == 0){
return 0;
}else{
return(long *)(dec % 2 + (10 * *convert(dec / 2)));
}
}
char* long_enough(char* num){
char* have_one = "0000";
char* have_two = "0000";
char* have_three = "000";
char* have_four = "00";
char* have_five = "0";
if(strlen(num) == 2){
strcat(have_one, num);
}else if(strlen(num) == 3){
strcat(have_two, num);
}else if(strlen(num) == 4){
strcat(have_three, num);
}else if(strlen(num) == 5){
strcat(have_four, num);
}else if(strlen(num) == 6){
strcat(have_five, num);
}
}
char main(){
int i;
int count = -1;
printf("\n");
for(i = 0; i < 5; i++){
count++;
long* binNum = (long *)(convert(count));
char* new;
char done = sprintf(new, "%d", binNum);
long_enough((char *)(intptr_t)done);
printf("%s\n", long_enough((char *)(intptr_t)done));
}
}
I think it has to do with your handling of pointers. #Pete Becker suggestion should get get you started but what also jumped out at me was this line:
return(long *)(dec % 2 + (10 * *convert(dec / 2)));
Here you are multiplying by the raw memory of the convert function result. If your intent is to raise to a power, note that there is no exponent operator in C. Do raise to a power, you'll need to #include <math.h> and use the pow(x,e) function.
You'll definitely want to read up on the pointer and value semantics in C. I'd recommend the book The C Programming Language by Brian W. Kernighan & Dennis M. Ritchie (the creators of the language). It is concise and will likely get you further, faster than a lot of the other books out there.
Are you using a long* to point nowhere?
It makes no sense. A pointer is meant to point to a memmory region and this memory region must have been allocated (either stack or heap).
It makes no sense that you are multiplying a binary number by 10 either.
You need to clarify your thought.
When you say you are making a "binary counter", think first about what it means. Given the code you posted, it looks like you should split your problem in two parts:
Count in binary.
Show the value in a human readable manner.
Once you've splitted the problem in two, I'll help you with one and let the other on your own.
Convert a number into binary:
Well, computer numbers are already binary by construction. Let's suppose you need, for any didactic reason, to reinvent the wheel in such a way that you can address individual values.
You have basically two options: use an array or use a bit-mask.
By using an array you'll waste more memory but printing the result will be easier.
By using a bit-mask you basically will have to allocate a single integer (or even char since you just need 6 bits) and shift it left while testing the original number.
// Example using bit-masks / bit-shifts into an uchar.
unsigned char to_bin6( unsigned int number )
{
unsigned char bin6 = 0;
// Left align and Clear out extra bits since we only care about the lowest 6.
number <<= ( 8 * sizeof( unsigned int ) ) - 6;
for ( int count = 6; count; --count )
bin6 <<= number;
return bin6;
}
Now with arrays.
// Example using char array.
// Array needs to have an additional element for the EoS (end of string) marker.
void to_bin6( unsigned int number, unsigned char bin6[ 7 ] )
{
// Fills the output buffer in the same direction you'd expect to read.
for ( int count = 5; count >= 0; --count )
bin6[ count ] = ( number & ( 1 << count ) ) ?
'1' : '0'; // Feeds character '1' or '0' according to bit value.
bin6[ 6 ] = '\0'; // EoS: Note this is NOT the same as '0'.
}
Show a number as binary for human reading:
That's the part I'll leave for you.
Hint: using array it is very easy.
Tell me if you need more.

Conversion of integer to char array in C

I'm developing an ARM embedded application. I'm kind of stuck on a silly problem - I have an array of unsigned 8-bit integers:
uint8_t days[42] = { 0 };
It's initialized with some data - the initialization algorithm introduces a lot of variables confusing and irrelevant to the problem, so I will not repost it here. I see this array in the debugger variable watch, and I'm certain it is filled with integer values from 0 to 31.
I'd like to take any element of this array, say 15th, and convert it to char* so that it can be displayed on my LCD screen. I rewrite it using sprintf function:
char d[3] = { '0', '0', '0' };
sprintf(d, "%d", days[15]);
Just one note: no, I can't use the stdlib itoa() function, because it does not conform to MISRA-C standards, which I am obliged to follow.
As a result, I only get a binary zero value in my d buffer. Any ideas?
For MISRA-C compliance, you can certainly not use sprintf() or anything else from stdio.h either. You generally want to avoid sprintf like the plague on any embedded system anyhow.
Writing a simple decimal integer to string conversion routine is quite basic stuff... here's my attempt of a MISRA-C (2004 and 2012) compatible version:
#include <stdint.h>
void dec_to_str (char* str, uint32_t val, size_t digits);
int main (void)
{
char str[3u + 1u]; // assuming you want null terminated strings?
dec_to_str(str, 31u, 3u);
return 0;
}
void dec_to_str (char* str, uint32_t val, size_t digits)
{
size_t i=1u;
for(; i<=digits; i++)
{
str[digits-i] = (char)((val % 10u) + '0');
val/=10u;
}
str[i-1u] = '\0'; // assuming you want null terminated strings?
}
Note: the uint32_t variable could get swapped out for an uint8_t, but then you need to add type casts all over the place, to prevent implicit type promotions, as required by MISRA. The code will then turn really ugly, like this:
str[digits-i] = (char)(uint8_t)((uint8_t)(val % 10u) + '0');
The only sane thing to do then, is to split that mess into several lines:
uint8_t ch = (uint8_t)(val % 10u);
ch = (uint8_t)(ch + '0');
str[digits-i] = (char)ch;
#include "stdafx.h"
#include <stdio.h>
int days[2] = {12,14};
char d[3] = {'0', '0', 0};
int _tmain(int argc, _TCHAR* argv[])
{
d[0] = days[1] / 10 + 0x30; // convert 10's digit to ascii
d[1] = days[1] % 10 + 0x30; // convert 1's digit to ascii
// Debugging help
printf(d);
getchar();
return 0;
}

conversion in c

I'm new to C and I need to write a function in c which converts an integer to a string in the specified base and print it.
If I were given an input value of 1234 (base 10) it should return 2322 (base 8).
Here is the code structure I'm currently working on:
void int2ascii(int value, int base){
int a=0;
if (value > base) {
a = a + int2char(value); //recursive case
int2ascii(value/base, base); //base case
}
printf("%s\n",a);
}
The program won't run, can someone enlighten me?
Thanks
Analysis of your program
I noted first off that a is declared int, but it was being passed to printf with %s as the format specifier. %s designates the associated argument will be a string, which a is not. The result will be undefined behavior, and is a possible cause for your crash.
You do not specify what int2char() does, but let's assume that it converts a numeric "digit" into a corresponding char value. With that in mind, let us suppose its implementation is similar to:
int int2char(int d) {
return "0123456789abcdefghijklmnopqrstuvwxyz"[d];
}
In your code, you pass value to int2char(). In my hypothetical implementation, this would cause out-of-bounds access of the array, and thus undefined behavior. This is indicates a logic error, and another possible cause for your crash.
I note that if value is less than base, a remains 0. Probably, you really mean to compute a value for a even when value is less than base. This indicates another logic error.
Base conversion
The number dKdK-1 .. d0, where each di is in (0 .. 9), is a short form for &Sum;di×10i. To discover the base 10 digits of a number N, the process is:
di = ⌊N / 10i⌋ mod 10
But, as it turns out, you can replace 10 with some other base number to compute the digits for a number in that base:
di = ⌊N / Bi⌋ mod B
In your code, the recursive call that divides by the base represents the first part of the calculation. However, in your calculation of a, you were missing the "mod" part of the calculation.
Solution 1
Assuming base is from 2 to 36, and that your int2char(d) does something more or less as illustrated earlier:
void int2ascii(int value, int base){
int a=0;
a = a + int2char(value%base);
if (value > base) {
int2ascii(value/base, base);
}
printf("%c",a);
}
Because you are not passing a into your recursive call, you can only use it to store the current digit to be printed. So, move the code to store the value in a out of the if check, since you always want a sensible value to print at the end. The digit in a is in the radix base, so you need the modulus result to get the right digit value. Since a represents a character, change the format string to match, and remove the \n so that all the digits end up on the same line.
Solution 2
The first solution is an attempt to leave most of your original code intact. Since a is initialized to 0, the extra addition does not make it incorrect. But, since the print doesn't happen until the very end, the value doesn't really need to be stored at all, and can be calculated at the point you actually want to print it. With that in mind, the program can be simplified to:
void int2ascii(int value, int base){
if (value > base) {
int2ascii(value/base, base);
}
printf("%c",int2char(value%base));
}
#include <stdio.h>
#include <limits.h>
char *int2ascii_aux(int n, int base, char *s){
//base {x| 2 <= x <= 36 }
static const char *table = "0123456789abcdefghijklmnopqrstuvwxyz";
if(n){
*--s = table[n % base];
return int2ascii_aux(n/base, base, s);
} else {
return s;
}
}
char *int2ascii(int n, int base){
//base {x| 2<= x <= 36 }
static char s[sizeof(int)*CHAR_BIT+1];
if(n <= 0){
*s = '0';
return s;
}
if(base < 2 || base > 36){
*s = '\0';
return s;
}
return int2ascii_aux(n, base, s + sizeof(s) -1);
}
int main(){
printf("%s\n", int2ascii(1234, 8));
return 0;
}

How to manually convert decimal value to hexadecimal string in C?

n.b. I know that this question has been asked on StackOverflow before in a variety of different ways and circumstances, but the search for the answer I seek doesn't quite help my specific case. So while this initially looks like a duplicate of a question such as How can I convert an integer to a hexadecimal string in C? the answers given, are accurate, but not useful to me.
My question is how to convert a decimal integer, into a hexadecimal string, manually. I know there are some beat tricks with stdlib.h and printf, but this is a college task, and I need to do it manually (professor's orders). We are however, permitted to seek help.
Using the good old "divide by 16 and converting the remainder to hex and reverse the values" method of obtaining the hex string, but there must be a big bug in my code as it is not giving me back, for example "BC" for the decimal value "188".
It is assumed that the algorithm will NEVER need to find hex values for decimals larger than 256 (or FF). While the passing of parameters may not be optimal or desirable, it's what we've been told to use (although I am allowed to modify the getHexValue function, since I wrote that one myself).
This is what I have so far:
/* Function to get the hex character for a decimal (value) between
* 0 and 16. Invalid values are returned as -1.
*/
char getHexValue(int value)
{
if (value < 0) return -1;
if (value > 16) return -1;
if (value <= 9) return (char)value;
value -= 10;
return (char)('A' + value);
}
/* Function asciiToHexadecimal() converts a given character (inputChar) to
* its hexadecimal (base 16) equivalent, stored as a string of
* hexadecimal digits in hexString. This function will be used in menu
* option 1.
*/
void asciiToHexadecimal(char inputChar, char *hexString)
{
int i = 0;
int remainders[2];
int result = (int)inputChar;
while (result) {
remainders[i++] = result % 16;
result /= (int)16;
}
int j = 0;
for (i = 2; i >= 0; --i) {
char c = getHexValue(remainders[i]);
*(hexString + (j++)) = c;
}
}
The char *hexString is the pointer to the string of characters which I need to output to the screen (eventually). The char inputChar parameter that I need to convert to hex (which is why I never need to convert values over 256).
If there is a better way to do this, which still uses the void asciiToHexadecimal(char inputChar, char *hexString) function, I am all ears, other than that, my debugging seems to indicate the values are ok, but the output comes out like \377 instead of the expected hexadecimal alphanumeric representation.
Sorry if there are any terminology or other problems with the question itself (or with the code), I am still very new to the world of C.
Update:
It just occurred to me that it might be relevant to post the way I am displaying the value in case its the printing, and not the conversion which is faulty. Here it is:
char* binaryString = (char*) malloc(8);
char* hexString = (char*) malloc(2);
asciiToBinary(*(asciiString + i), binaryString);
asciiToHexadecimal(*(asciiString + i), hexString);
printf("%6c%13s%9s\n", *(asciiString + i), binaryString, hexString);
(Everything in this code snip-pit works except for hexString)
char getHexValue(int value)
{
if (value < 0) return -1;
if (value > 16) return -1;
if (value <= 9) return (char)value;
value -= 10;
return (char)('A' + value);
}
You might wish to print out the characters you get from calling this routine for every value you're interested in. :) (printf(3) format %c.)
When you call getHexValue() with a number between 0 and 9, you return a number between 0 and 9, in the ASCII control-character range. When you call getHexValue() with a number between 10 and 15, you return a number between 65 and 75, in the ASCII letter range.
The sermon? Unit testing can save you hours of time if you write the tests about the same time you write the code.
Some people love writing the tests first. While I've never had the discipline to stick to this approach for long, knowing that you have to write tests will force you to write code that is easier to test. And code that is easier to test is less coupled (or 'more decoupled'), which usually leads to fewer bugs!
Write tests early and often. :)
Update: After you included your output code, I had to comment on this too :)
char* binaryString = (char*) malloc(8);
char* hexString = (char*) malloc(2);
asciiToBinary(*(asciiString + i), binaryString);
asciiToHexadecimal(*(asciiString + i), hexString);
printf("%6c%13s%9s\n", *(asciiString + i), binaryString, hexString);
hexString has been allocated one byte too small to be a C-string -- you forgot to leave room for the ASCII NUL '\0' character. If you were printing hexString by the %c format specifier, or building a larger string by using memcpy(3), it might be fine, but your printf() call is treating hexString as a string.
In general, when you see a
char *foo = malloc(N);
call, be afraid -- the C idiom is
char *foo = malloc(N+1);
That +1 is your signal to others (and yourself, in two months) that you've left space for the NUL. If you hide that +1 in another calculation, you're missing an opportunity to memorize a pattern that can catch these bugs every time you read code. (Honestly, I found one of these through this exact pattern on SO just two days ago. :)
Is the target purely hexadecimal, or shall the function be parametizable. If it's constrained to hex, why not exploit the fact, that a single hex digit encodes exactly four bits?
This is how I'd do it:
#include <stdlib.h>
#include <limits.h> /* implementation's CHAR_BIT */
#define INT_HEXSTRING_LENGTH (sizeof(int)*CHAR_BIT/4)
/* We define this helper array in case we run on an architecture
with some crude, discontinous charset -- THEY EXIST! */
static char const HEXDIGITS[0x10] =
{'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
void int_to_hexstring(int value, char result[INT_HEXSTRING_LENGTH+1])
{
int i;
result[INT_HEXSTRING_LENGTH] = '\0';
for(i=INT_HEXSTRING_LENGTH-1; value; i--, value >>= 4) {
int d = value & 0xf;
result[i] = HEXDIGITS[d];
}
for(;i>=0;i--){ result[i] = '0'; }
}
int main(int argc, char *argv[])
{
char buf[INT_HEXSTRING_LENGTH+1];
if(argc < 2)
return -1;
int_to_hexstring(atoi(argv[1]), buf);
puts(buf);
putchar('\n');
return 0;
}
I made a librairy to make Hexadecimal / Decimal conversion without the use of stdio.h. Very simple to use :
char* dechex (int dec);
This will use calloc() to to return a pointer to an hexadecimal string, this way the quantity of memory used is optimized, so don't forget to use free()
Here the link on github : https://github.com/kevmuret/libhex/
You're very close - make the following two small changes and it will be working well enough for you to finish it off:
(1) change:
if (value <= 9) return (char)value;
to:
if (value <= 9) return '0' + value;
(you need to convert the 0..9 value to a char, not just cast it).
(2) change:
void asciiToHexadecimal(char inputChar, char *hexString)
to:
void asciiToHexadecimal(unsigned char inputChar, char *hexString)
(inputChar was being treated as signed, which gave undesirable results with %).
A couple of tips:
have getHexValue return '?' rather than -1 for invalid input (make debugging easier)
write a test harness for debugging, e.g.
int main(void)
{
char hexString[256];
asciiToHexadecimal(166, hexString);
printf("hexString = %s = %#x %#x %#x ...\n", hexString, hexString[0], hexString[1], hexString[2]);
return 0;
}
#include<stdio.h>
char* inttohex(int);
main()
{
int i;
char *c;
printf("Enter the no.\n");
scanf("%d",&i);
c=inttohex(i);
printf("c=%s",c);
}
char* inttohex(int i)
{
int l1,l2,j=0,n;
static char a[100],t;
while(i!=0)
{
l1=i%16;
if(l1>10)
{
a[j]=l1-10+'A';
}
else
sprintf(a+j,"%d",l1);
i=i/16;
j++;
}
n=strlen(a);
for(i=0;i<n/2;i++)
{
t=a[i];
a[i]=a[n-i-1];
a[n-i-1]=t;
}
//printf("string:%s",a);
return a;
//
}
In complement of the other good answers....
If the numbers represented by these hexadecimal or decimal character strings are huge (e.g. hundreds of digits), they won't fit in a long long (or whatever largest integral type your C implementation is providing). Then you'll need bignums. I would suggest not coding your own implementation (it is tricky to make an efficient one), but use an existing one like GMPlib

How to convert integer to char without C library?

In a c programming exercise I am asked to convert an int to char without using the C library.
Any idea how to go about it?
edit: what I mean by int is the built in C/C++ type
Thanks.
Cast it?
char c = (char)i;
Or maybe you meant this?
char c = (char)('0' + i);
I'm sure this isn't what you mean though... I'm guessing you want to create a string (char array)? If so, then you need to convert it one digit at a time starting with the least significant digit. You can do it recursively, in pseudo-code:
function convertToString(i)
if i < 10
return convertDigitToChar(i)
else
return convertDigitToString(i / 10) concat convertDigitToChar(i % 10)
Here / is integer division and % is integer modulo. You also need to handle negative numbers. This can be done by checking first if you have a negative number, calling the function on the aboslute value and adding the minus sign if necessary.
In C for performance you would probably implement this with a loop instead of using recursion, and by directly modifying the contents of a character array instead of concatenating strings.
If you really want a string:
#include <stdio.h>
char *tochar(int i, char *p)
{
if (i / 10 == 0) {
// No more digits.
*p++ = i + '0';
*p = '\0';
return p;
}
p = tochar(i / 10, p);
*p++ = i % 10 + '0';
*p = '\0';
return p;
}
int main()
{
int i = 123456;
char buffer[100];
tochar(i, buffer);
printf("i = %s\n", buffer);
}
For completeness, if the task is to convert int to string as anthares suspects, you can use Mark's second answer to convert each digit of the integer. To get each digit, you have to look into the division and modulo operators.

Resources