Output does not print the correct variable addresses - arrays

Despite using double as datatype and correct format specifiers the output does not print the correct variable addresses output consists of just zeros
#include <stdio.h>
void main() {
double a[5] = { 6.0, 7.0, 8.0, 9.0, 10.0 };
double *p;
p = a;
printf("%lf \n", p);
for (int i = 0; i < 5; i++) {
printf("%lf \n", p++);
}
}
Output:
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000

I fixed it with 2 simple changes, described in the comments.
#include<stdio.h>
void main()
{
double a[5]={6.0,7.0,8.0,9.0,10.0};
double *p;
p=a;
printf("%p \n",p); // Changed formatter to %p to print addresses
for(int i=0;i<5;i++)
{
printf("%p \n",p++); // Changed formatter to %p to print addresses
}
}
Output
0x7fffdd887250
0x7fffdd887250
0x7fffdd887258
0x7fffdd887260
0x7fffdd887268
0x7fffdd887270

These calls of printf
printf("%lf \n",p);
and
printf("%lf \n",p++);
invokes undefined behavior because there is used the wrong conversion specifier "%lf" (where by the way the length modifier has no effect even when used with object of the type double) with pointers.
Either you should use the conversion specifier %p like
printf("%p \n", ( void * )p);
and
printf("%p \n", ( void * )p++);
Or if you want to output addresses as integers you can include headers <stdint.h> and <inttypes.h> (the last header already includes the first header and write
#include <stdint.h>
#include <inttypes.h>
//...
printf("%" PRIuPTR "\n", ( uintptr_t )p);
and
printf("%" PRIuPTR "\n", ( uintptr_t )p++);
Pay attention to that according to the C Standard the function main without parameters shall be declared like
int main( void )
Here is a demonstration program.
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main( void )
{
double a[] = { 6.0, 7.0, 8.0, 9.0, 10.0 };
const size_t N = sizeof( a ) / sizeof( *a );
double *p = a;
printf( "%p", ( void * )p );
printf( " <-> %" PRIuPTR "\n", ( uintptr_t )p );
for ( size_t i = 0; i < N; i++ )
{
printf( "%p", ( void * )p );
printf( " <-> %" PRIuPTR "\n", ( uintptr_t )p++ );
}
}
The program output is
00AFFE40 <-> 11533888
00AFFE40 <-> 11533888
00AFFE48 <-> 11533896
00AFFE50 <-> 11533904
00AFFE58 <-> 11533912
00AFFE60 <-> 11533920

maybe make the printf of for loop like this:
for(int i=0;i<5;i++)
{
printf("%lf \n",p[i]++);
}
OUTPUT:
0.000000
6.000000
7.000000
8.000000
9.000000
10.000000

Related

Code using variadic arguments not giving the expected output

I have the following example code
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
void myprint(char *inizio, ...);
int main(void)
{
myprint("Inizio", 2, 3.0, 4, 5.0, 'c');
return(0);
}
void myprint(char *inizio, ...)
{
va_list argPoint;
int pi;
char pc;
double pd;
va_start(argPoint, inizio);
pi=va_arg(argPoint,int);
printf("Int = %d\n", pi);
pi=va_arg(argPoint,int);
printf("Int = %d\n", pi);
pd=va_arg(argPoint,double);
printf("Int = %f\n", pd);
/* need a cast here since va_arg only takes fully promoted types
pc=va_arg(argPoint,char); */
pc=(char)va_arg(argPoint,int);
printf("Int = %c\n", pc);
pd=va_arg(argPoint,double);
printf("Int = %f\n", pd);
pi=va_arg(argPoint,int);
printf("Int = %d\n", pi);
va_start(argPoint, inizio);
pi=va_arg(argPoint,int);
printf("Int = %d\n", pi);
va_end(argPoint);
}
I am getting the following output:
Int = 2
Int = 0
Int = 0.000000
Int =
Int = 0.000000
Int = 117
Int = 2
The answer according to my handout should be:
Int = 2
Int = 4
Int = 3.000000
Int = c
Int = 5.000000
Int = 1235099264
Int = 2
Why is it not working? I am using Codeblocks by the way, just in case.
Additionally what does the comment " need a cast here since va_arg only takes fully promoted types pc=va_arg(argPoint,char); " means? va_arg(argPoint,char) is supposed to return a char, I don't see why they do pc=(char)va_arg(argPoint,int) instead, the (char) seems redundant.

FILE * is reading zeros into a 'double' variable from input text file after reading previous entries correctly

The assignment at hand is to read values from an input file "as5input.txt" and do some basic linear calculations on the values to later write them to another output text file. Using 'fscanf()' it successfully reads the first two lines of data and then proceeds to only read zeros when it should be reading the actual values.
I have tried different formattings on fscanf and tried reading directly to see the value it was reading. I made sure there were no '\n' or ' ' characters in the input file that could cause an issue. I also tried making a new text file with the same format to make sure there were not any weird bugs with the file. However, it is still reading zeros.
I think it has something to do with reading an int and then reading a double but it does not make sense why it would be so.
This is the text file I am working with:
as5input.txt
2.0 5.0
6
1.0 2.0 4.0 8.0 16.0 31.0
And this is the program that interacts with it:
as5.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct instance_struct
{
int count;
float m, b;
double * x, * y;
};
typedef struct instance_struct instance;
void instance_print(instance *is, FILE * ofp)
{
int i;
fprintf(ofp, " y = %f x + %f\n", is->m, is->b);
for (i = 0; i < is -> count; i++)
{
fprintf(ofp, " x: %f y: %f\n", is->x[i], is->y[i]);
}
}
instance * make_instance(int count, float m, float b) {
instance * is = (instance *)malloc(sizeof(instance));
is -> m = m;
is -> b = b;
is -> count = count;
is -> x = (double *)malloc(sizeof(double) * count);
is -> y = (double *)malloc(sizeof(double) * count);
return is;
}
int main(void)
{
int i, count;
float m, b;
FILE *ifp, *ofp;
ifp = fopen("as5input.txt", "r");
ofp = fopen("out.txt", "w");
fscanf(ifp, "%f %f %d", &m, &b, &count);
double temp;
instance * is = make_instance(count, m, b);
for (i = 0; i < count; i++) {
fscanf(ifp, "%f", &temp);
printf("%f\n", temp);
is -> x[i] = temp;
is -> y[i] = m * temp + b;
}
instance_print(is, ofp);
fclose(ifp);
fclose(ofp);
return 0;
}
This is what comes out on the output file:
out.txt
y = 2.000000 x + 5.000000
x: 0.000000 y: 5.000000
x: 0.000000 y: 5.000000
x: 0.000000 y: 5.000000
x: 0.000000 y: 5.000000
x: 0.000000 y: 5.000000
x: 0.000000 y: 5.000000
And this is what comes out from the printf on line 51:
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
I might be missing something very simple but it is just weird that it reads the slope, intercept and count (m, b, count) correctly. Any help or advice would be greatly appreciated.
double temp;
instance * is = make_instance(count, m, b);
for (i = 0; i < count; i++) {
fscanf(ifp, "%f", &temp);
...
}
You're using %f as the format specifier but passing a double*, not a float*. Increase your compiler's warnings and you'll probably see a warning like this (-Wall for gcc/clang for example):
<source>:50:27: warning: format specifies type 'float *' but the argument has type 'double *' [-Wformat]
fscanf(ifp, "%f", &temp);
~~ ^~~~~
%lf
The solution is to either make temp a float or use %lf as the format specifier.
Note that the %f specifier for printf is for a double, as floats are passed as doubles to functions taking a variable number of arguments. This doesn't apply to pointers.

fscanf for int and float returns large value for int, and NAN for float

I am trying to store a series of values from a configuration file which have data types of int and float. I'm not sure why, but when I print the values inside the array, the int value returns a large number, and the floats return NAN.
Configuration file:
1666 -0.314913523 0.999804843
1667 -0.337279687 0.999865966
1703 -0.323162231 0.999774194
1704 -0.311984064 0.99964375
1705 -0.311984064 0.99964375
1706 -0.313381260 0.999671436
1707 -0.313170802 0.999558174
My code:
#include <iostream>
using namespace std;
#define NUM_ITEMS 50
int main()
{
FILE *fp;
fp = fopen("config.conf","r");
int a[NUM_ITEMS][NUM_ITEMS];
float b[NUM_ITEMS][NUM_ITEMS];
float c[NUM_ITEMS][NUM_ITEMS];
int i = 0;
while(fscanf(fp,"%i\t%f\t%f", a[i], b[i], c[i]) != EOF)
{
printf("%i %f %f\n", a[i], b[i], c[i]);
i++;
}
fclose(fp);
}
output:
1149516976 -nan 0.000000
1149517176 -nan 0.000000
1149517376 -nan 0.000000
1149517576 -nan 0.000000
1149517776 -nan 0.000000
1149517976 -nan 0.000000
1149518176 -nan 0.000000
int a[NUM_ITEMS][NUM_ITEMS];
float b[NUM_ITEMS][NUM_ITEMS];
float c[NUM_ITEMS][NUM_ITEMS];
This makes a, b, and c arrays of arrays, so a[i] is an array. You want:
int a[NUM_ITEMS];
float b[NUM_ITEMS];
float c[NUM_ITEMS];
So that a is an array of ints and now a[i] is an int. You need to pass the address to scanf though.
Here's the code with all major issues fixed:
#include <iostream>
#define NUM_ITEMS 50
int main()
{
FILE *fp;
fp = fopen("config.conf","r");
if (fp == NULL)
return -1;
int a[NUM_ITEMS];
float b[NUM_ITEMS];
float c[NUM_ITEMS];
int i = 0;
while(fscanf(fp,"%i\t%f\t%f", &a[i], &b[i], &c[i]) == 3)
{
printf("%i %f %f\n", a[i], b[i], c[i]);
i++;
}
fclose(fp);
}

Print correct format from double value to hexadecimal

#include <stdio.h>
typedef unsigned char*pointer;
void show_bytes(pointer start, size_t len)
{
size_t i;
for (i = 0; i < len; i++)
printf("%p\t0x%04x\n",start+i, start[i]);
printf("\n");
}
int main()
{
double a = 4.75;
printf("Double demo by %s on %s %s\n", "Toan Tran", __DATE__, __TIME__);
printf("Double a = %.2f (0x%08x)\n", a, a);
show_bytes((pointer) &a, sizeof(double));
}
Output:
Double demo by Toan Tran on Nov 8 2018 11:07:07
Double a = 4.75 (0x00000100)
0x7ffeee7a0b38 0x0000
0x7ffeee7a0b39 0x0000
0x7ffeee7a0b3a 0x0000
0x7ffeee7a0b3b 0x0000
0x7ffeee7a0b3c 0x0000
0x7ffeee7a0b3d 0x0000
0x7ffeee7a0b3e 0x0013
0x7ffeee7a0b3f 0x0040
For this line:
printf("Double a = %.2f (0x%08x)\n", a, a);
I want it to print out the result of start[i]
The return hexadecimal is not the right value for double.
I want it to return 0x40130000000000...
Please help.
The %x format specifier is expecting an unsigned int argument, but you're passing in a double. Using the wrong format specifier invokes undefined behavior.
To print the representation of a double, you need to print each individual byte as hex using a character pointer. This is exactly what you're doing in show_bytes, and is the proper way to do this.
Also, when printing a pointer with the %p format specifier, you should cast the pointer to void *, which is what %p expects. This is one of the rare cases where a cast to void * is needed.
You might be tempted to do something like this:
printf("%llx", *((unsigned long long *)&a));
However this is a violation of the strict aliasing rule. You would need to use memcpy to copy the bytes to the other type:
static_assert(sizeof(unsigned long long) == sizeof(double));
unsigned long long b;
memcpy(&b, &a, sizeof(a));
printf("%llx", b);
You can also do this with a union:
union dval {
double d;
unsigned long long u;
};
union dval v;
v.d = d;
printf("%llx", v.u);
To allow printing a hex dump of any object, pass its address and length.
void show_bytes2(void *start, size_t size) {
int nibble_width_per_byte = (CHAR_BIT + 3) / 4; // Often 2
unsigned char *mem = start;
// Highest bytes first
for (size_t i = size; i>0; ) {
printf("%0*x", nibble_width_per_byte, mem[--i]);
}
printf("\n");
// Lowest bytes first
while (size--) {
printf("%0*x", nibble_width_per_byte, *mem++);
}
printf("\n");
}
Use "%a" to print the significand of the double in hexadecimal.
int main() {
double a = 4.75;
printf("Double a = %a %e %f %g\n", a, a, a, a);
show_bytes2(&a, sizeof a);
}
Output
Double a = 0x1.3p+2 4.750000e+00 4.750000 4.75
4013000000000000 // I want it to return 0x40130000000000...
0000000000001340

Getting arguments from the stack in c

I just started to learn c and I was trying to create a function that gets it's arguments from the stack when I know all the arguments are from the same type, but it worked only for int.
This is what I did:
void Test1(double first_arg, ...)
{
double *a = &first_arg;
printf("arg[0]: %f\narg[1]: %f \narg[2]: %f\n", a[0], a[1], a[2]);
}
void Test2(int first_arg, ...)
{
int *a = &first_arg;
printf("arg[0]: %d\narg[1]: %d \narg[2]: %d\n", a[0], a[1], a[2]);
}
int main()
{
printf("Test1:\n");
Test1(1.0, 2.0, 3.0);
printf("\nTest2:\n");
Test2(1, 2, 3);
return 0;
}
Console:
Test1:
arg[0]: 1.000000
arg[1]: 0.000000
arg[2]: 0.000000
Test2:
arg[0]: 1
arg[1]: 2
arg[2]: 3
What am I missing here? And what should I do to fix this.
The way arguments are passed to a function are implementation dependent. To read variable arguments in a portable way, you need to use the stdarg family of functions.
#include <stdio.h>
#include <stdarg.h>
void Test1(double first_arg, ...)
{
printf("arg[0]=%f\n", first_arg);
va_list ap;
va_start(ap, first_arg);
double arg1 = va_arg(ap, double);
printf("arg[1]=%f\n", arg1);
double arg2 = va_arg(ap, double);
printf("arg[2]=%f\n", arg2);
va_end(ap);
}
int main()
{
printf("Test1:\n");
Test1(1.0, 2.0, 3.0);
return 0;
}

Resources