So I am new to using GDB and I am using the following program as an excercise
#include <stdio.h>
#include <stdlib.h>
int main() {
unsigned int value1, abs_value1, abs_value2, abs_value3;
int value2, value3;
char myarray[10];
printf("Enter 10 characters:");
fgets(myarray, 11, stdin);
printf("Enter an integer between 0 and 10,000:");
scanf("%d", &value1);
abs_value1 = abs(value1);
printf("Enter an integer between -10,000 and 0:");
scanf("%d", &value2);
abs_value2 = abs(value2);
printf("Enter an integer between -10,000 and 10,000:");
scanf("%d", &value3);
abs_value3 = abs(value3);
// set breakpoint here
return 0;
}
The values I've entered are as follows...
myarray[10] = "characters"
value1 = 578
value2 = -1123
value3 = 999
After running some commands I got the following output...
x/1x myarray : 0x63
x/1c myarray : 99 'c'
x/1s myarray : "characters"
x/1d &abs_value1 : 578
x/1x &value1 : 0x00000242
x/1d &abs_value2 : 1123
x/1x &value2 : 0xfffffb9d
x/1d &abs_value3 : 999
x/1x &value3 :0x000003e7
x/1c &value1 : 66 'B'
x/1c &value2 : -99 '\235'
So my question is, without looking at the code and using only the previous commands, can we tell if value1, value2, and value3 are signed or unsigned?
To my knowledge I don't think there is enough information to tell if they are signed or unsigned. My first instinct was to look for negative values but since we are taking the absolute value of our variables there is no way to be certain if the the value began as a negative number based of just looking at the commands.
Are there some different ways we might be able to deduce if the variables are signed or unsigned?
Are there some different ways we might be able to deduce if the variables are signed or unsigned?
With debug info enabled this is quite easy. You can use ptype command but you should build the binary with -g option to make it work.
(gdb) ptype value1
type = unsigned int
(gdb) ptype abs_value1
type = unsigned int
(gdb) ptype abs_value2
type = unsigned int
(gdb) ptype abs_value3
type = unsigned int
(gdb) ptype value2
type = int
(gdb) ptype value3
type = int
(gdb) ptype myarray
type = char [10]
(gdb)
Related
I am using the following to print out numbers from an array in hex:
char buff[1000];
// Populate array....
int i;
for(i = 0; i < 1000; ++i)
{
printf("[%d] %02x\n", i,buff[i]);
}
but I sometimes print weird values:
byte[280] 00
byte[281] 00
byte[282] 0a
byte[283] fffffff4 // Why is this a different length?
byte[284] 4e
byte[285] 66
byte[286] 0a
Why does this print 'fffffff4'?
Use %02hhx as the format string.
From CppReference, %02x accepts unsigned int. When you pass the arguments to printf(), which is a variadic function, buff[i] is automatically converted to int. Then the format specifier %02x makes printf() interprets the value as int, so potential negative values like (char)-1 get interpreted and printed as (int)-1, which is the cause of what you observed.
It can also be inferred that your platform has signed char type, and a 32-bit int type.
The length modifier hh will tell printf() to interpret whatever supplied as char type, so %hhx is the correct format specifier for unsigned char.
Alternatively, you can cast the data to unsigned char before printing. Like
printf("[%d] %02x\n", i, (unsigned char)buff[i]);
This can also prevent negative values from showing up as too long, as int can (almost) always contain unsigned char value.
See the following example:
#include <stdio.h>
int main(){
signed char a = +1, b = -1;
printf("%02x %02x %02hhx %02hhx\n", a, b, a, b);
return 0;
}
The output of the above program is:
01 ffffffff 01 ff
Your platform apparantly has signed char. On platforms where char is unsigned the output would be f4.
When calling a variadic function any integer argument smaller than int gets promoted to int.
A char value of f4 (-12 as a signed char) has the sign bit set, so when converted to int becomes fffffff4 (still -12 but now as a signed int) in your case.
%x02 causes printf to treat the argument as an unsigned int and will print it using at least 2 hexadecimal digits.
The output doesn't fit in 2 digits, so as many as are required are used.
Hence the output fffffff4.
To fix it, either declare your array unsigned char buff[1000]; or cast the argument:
printf("[%d] %02x\n", i, (unsigned char)buff[i]);
I have an integer
int value = 0x12345678;
I want to take the first half and the second half and place the two halves into two separate integers
e.g.
int value2 = 0x1234;
int value3 = 0x5678;
How would I go about doing this?
Shift the number by 16 bits to the right to get the first half.
int value2 = (value >> 16);
Use bitwise & to get the second half.
int value3 = (value & 0xFFFF);
Note that I changed this to using unsigned (to avoid sign-extension on 32-bit platforms for arbitrary values of value1)
unsigned value1 = 0x12345678;
unsigned value2 = value1 / 0x10000;
unsigned value3 = value1 % 0x10000;
I chose this method -- only caring about the int values here.
If you take care about the representation, you can also use shift operators and masks.
This question already has answers here:
Comparison operation on unsigned and signed integers
(7 answers)
Why is (sizeof(int) > -1) false? [duplicate]
(3 answers)
Closed 6 years ago.
unsigned long mynum = 7;
if(mynum > -1) // false
Why does this happen ? is it because -1 is an int, and when it gets "promoted" to unsigned long, it gets the maximum value of unsigned long ?
This might not be right but here's what i think:
When you execute the following code
unsigned long a = -8;
std::cout << a;
Since unsigned values can't be below 0, it will return the max value of an unsigned long - 8 or 4294967288 in this case.
And thats what happened to the -1 in your operation when it got converted to an unsigned long
unsigned variables has the maximum value they don't have a minus sign so the last bit is positive.
assigning a negative value to a unsigned will set the value to the corresponding signed value:
-1 and 255 has the same bitfield set:
#include <iostream>
int main()
{
unsigned char uc1 = 255; // 11111111
unsigned char uc2 = -1;
//signed : -1 : 11111111 : 1 1111111 : -128 + 127
//unsigned: 255: 11111111 : 1 1111111 : 128 + 127
if(uc1 == uc2)
std::cout << "uc1 = uc2" << std::endl;
return 0;
}
This is because of implicit typecast which is performed internally by compiler.
When the operation is going between two different types of variables the compiler itself typecasts (converts temporarily) the lower data type to higher datatype temporarily.
Here in your code -1 temporarily acts as unsigned long because implicit typecasting performed by compiler itself. It behaves as unsigned long because the other variable is pf that type.
here -1 is not treated as -1 but its treated as its equivalent as unsigned long.
This question already has answers here:
Signed to unsigned conversion in C - is it always safe?
(8 answers)
Closed 9 years ago.
#include <iostream>
int main ()
{
using namespace std;
unsigned int i = 4;
int a = -40;
cout<<a+i<<endl;
return 0;
}
Executing this gives me 4294967260
I know there's a conversion taking place, from a signed int to unsigned int,
but how and why this particular value?
I noticed it's close to the sum of | 2147483647 | + 2147483647
When an unsigned int and an int are added together, the int is first converted to unsigned int before the addition takes place (and the result is also an unsigned int).
-1, while being the first negative number, is actually equivalent to the largest unsigned number - that is, (unsigned int) -1 === UINT_MAX.
-2 in unsigned form is UINT_MAX - 1, and so on, so -40 === UINT_MAX - 39 === 4294967256 (when using 32bit ints).
Of course, adding 4 then gives your answer:
4294967256 + 4 = 4294967260.
This is a great quiz where you can learn some of the rules of integers in C (and similarly C++): http://blog.regehr.org/archives/721
Represent i and a in hexadecimal:
i = 4: 0x 0000 0004
a = -40: 0x FFFF FFD8
Following the implicit conversion rules of C++, a in a + i will be cast to unsigned int, that is, 4294967256. So a + i = 4294967260
Say, we get int A 333; int B 4444 and int C 5454 we want to concatenate them into one unsigned long long 000333 004444 005454 00 (with format like 0/1 int sign, int). How to do such formating in C++, and are there any C++11 tools that can simplify process?
You could make strings from the ints using std::to_string, concatenate as necessary, then convert to long long using std::stoll.
Do you just mean this?
unsigned int A = 333;
unsigned int B = 4444;
unsigned int C = 5454;
unsigned long long r = A*100000000000000ULL + B*100000000ULL + C*100ULL;
Proof it works: http://ideone.com/XWFdU