Difference between atoll and (long int)? - c++

Excuse me if this is a bad question. Most probably it is. But I am under the impression that (long int)[some string] should convert string into a long int. That doesn't seem to be the case as I just wrote a sample program.
#include <iostream>
#include <cstdlib>
using namespace std;
int main(int argc, char **argv)
{
int firstNum = atoll(argv[1]);
int secondNum = atoll(argv[2]);
int sum = firstNum + secondNum;
long int firstArg = (long int)argv[1];
long int secondArg = (long int)argv[2];
long int argSum = firstArg + secondArg;
cout << "The argSum is: " << argSum << ", which is same as sum: " << sum << endl;
}
I came under this impression because of a code I was reading given as under. An explanation would help me build some knowledge. Thanks.
srv.request.a = atoll(argv[1]);
srv.request.b = atoll(argv[2]);
if (client.call(srv))
{
ROS_INFO("Sum: %ld", (long int)srv.response.sum);
}

atoll is a function which parses a string to yield the numeric value it represents as a long long (which you then stuff into an int).
Casting, which is what (long int)arg[0] is doing, tells the compiler to interpret one value as another type. In your case, the thing you are trying to interpret is the pointer to a character, not the value that is represented by the string it points to the start of.

But I am under the impression that (long int)[some string] should convert string into a long int.
That is not correct.
What it does is take the pointer value that represents the string and convert it into a long int. There is no telling what that value would be from one run of the program to the next.
The use of atoll(argv[1]), on the other hand, does the proper extraction of the number from the string.

I am under the impression that (long int)[some string] should convert string into a long int.
You've misunderstood. Explicit conversion (aka cast) does nothing of the sort. When converting a "pointer to char" (which is the type of your string) into an integer will result in the integer value of the address that the pointer points to - possibly losing precision if the target integer type cannot represent the memory address value.
Difference between atoll and (long int)?
atoll converts a character string to an integer value based on what digits the contents of the string represents.
An explicit conversion has different behaviour depending on the type of the argument, but in case of character pointer, see the paragraph above.

(long int)[some string] is a cast, it does no actual processing of the data, it just tells the compiler to interpret whatever data [some string] is as if it was a long int, in this case you'll be seeing the offset of the string in memory, as a C string is just a pointer to some data.
atoll is a function which parses the string and converts the text to an integer value.

Related

Why does this segmentation fault?

I was trying to make a factorial program that takes input from the terminal but it doesn't work..
giving it anything but no arguments gives a segmentation fault
// factorial calculator
#include <iostream>
using namespace std;
long factorial(long a) {
if (a > 1)
return (a * factorial(a-1));
else
return 1;
}
int main(int argc, char *argv[]) {
long number = (long) argv[1];
cout << number << "! = " << factorial(number) << '\n';
return 0;
}
also for some reason number has the value of 140732199978159 when I do ./factorial 2
(all I got from attempting to find an answer by searching was that a segfault means that I'm accessing something I'm not supposed to. I don't understand where I've done that here.)
long number = (long) argv[1];
This takes argv[1] and casts it to long. argv is a char*[] (for simplicity, I'll assume it's the very similar type char** for this explanation). Hence, argv[1] is a char*. Casting a char* to long takes its address as a numerical value. That's a position in memory on your computer and not helpful for calculating the factorial.
Consider strtol, a built-in C++ function that does exactly what you want.
long number = std::strtol(argv[1], nullptr, 10);
10 is the numerical base (we do our math in base 10, generally). The second argument is optional and not necessary for our use case, so we pass nullptr since we don't need it.
(long) argv[1];
argv[1] is a const char *, a pointer to some unspecified number of characters.
Even if that character string happens to be "2", converting the pointer to a long value, like this, does not get you an actual number 2. That's not how C++ works. All this does is reinterpret the raw memory address, that the pointer is pointing to. You get, pretty much, a junk number, and attempting to compute its factorial results in equally meaningless results.
You'll need to use some suitable library function, like atol from the C library, or std::stol from the C++ library (with some overhead due to a temporary conversion to a std::string) in order to get the expected results.

Invalid conversion from char to const* char, What is wrong with the code?

i'm trying to write a function which takes one int parameter and returns sum of it's digits.For example, digital_root(123) will return 1+2+3 which is 6.And inside the for loop i can't convert individual character to integer..
it should be included that i used both atoi() and stoi() functions.What is wrong with the code?
int digital_root(int x)
{
int t = 0;
string str = to_string(x);
for(char& c : str){
t += atoi(c);
}
return t;
}
i expect the characters to convert to integer successfully.how can i do so?
Have a look at std::atoi, its argument is of type const char*, but you are passing a single char. There is no possible conversion from char to const char*, this is what the compiler complains about.
What you want instead is converting the char to an int by doing some ASCII math:
t += static_cast<int>(c) - '0';
But note that while this works, there is a better solution for this task. It doesn't require the conversion to a string, but instead relies on integer division solely, repeatedly using % 10.

Converting an integer to an hexadecimal unsigned char array in C++

I need to convert an integer int parameter to an hexadecimal unsigned char buffer[n].
If integer is for example 10 then the hexadecimal unsigned char array should be 0x0A
To do so I have the following code:
int parameter;
std::stringstream ss;
unsigned char buffer[];
ss << std::hex << std::showbase << parameter;
typedef unsigned char byte_t;
byte_t b = static_cast<byte_t>(ss); //ERROR: invalid static_cast from type ‘std::stringstream {aka std::basic_stringstream<char>}’ to type ‘byte_t {aka unsigned char}’
buffer[0]=b;
Does anyone know how to avoid this error?
If there is a way of converting the integer parameter into an hexadecimal unsigned char than doing first: ss << std::hex << std::showbase << parameter; that would be even better.
Consulting my psychic powers it reads you actually want to have a int value seen in it's representation of bytes (byte_t). Well, as from your comment
I want the same number represented in hexadecimal and assigned to a unsigned char buffer[n].
not so much psychic powers, but you should note hexadecimal representation is a matter of formatting, not internal integer number representation.
The easiest way is to use a union like
union Int32Bytes {
int ival;
byte_t bytes[sizeof(int)];
};
and use it like
Int32Bytes x;
x.ival = parameter;
for(size_t i = 0; i < sizeof(int); ++i) {
std::cout << std::hex << std::showbase << (int)x.bytes[i] << ' ';
}
Be aware to see unexpected results due to endianess specialities of your current CPU architecture.
Problem 1: buffer is of undetermined size in your snippet. I'll suppose that you have declared it with a sufficient size.
Problem 2: the result of your conversion will be several chars (at least 3 due to the 0x prefix). So you need to copy all of them. This won't work with an = unless you'd have strings.
Problem 3: your intermediary cast won't succeed: you can't hope to convert a complex stringstream object to a single unsigned char. Fortunately, you don't need this.
Here a possible solution using std::copy(), and adding a null terminator to the buffer:
const string& s = ss.str();
*copy(s.cbegin(), s.cend(), buffer)='\0';
Live demo

How does C++ interpret a cout with a '+' in it?

I've been moving back and forth with Java/C++ so I messed up with my console output and accidentally wrote lines like:
cout << "num" + numSamples << endl;
cout << "max" + maxSampleValue << endl;
Each of which gave me bits and pieces of other strings I had in my program. I realize my mistake now, but what was C++ interpreting those lines as so that they output different parts of different strings in my program?
There is a simple reason for this:
"num" and "max" are string literal. Their type is const char *.
Assuming numSamples is an integer, what you are doing is is pointer arithmetic.
You are basically printing a string that points to "num" + numSamples bytes.
If you did cout << "num" + 1 << endl this would print "um".
You probably figured it out, but the correct way to do this is: cout << "num" << numSamples << endl;
Also, you asked:
But what was C++ interpreting those lines as so that they output
different parts of different strings in my program?
As stated before, "num" is a string literal. Generally string literals sits in the same place in the binary program: .rodata. All other string literals sits in this region, so when you are advancing your pointer by a certain amount of bytes, you will likely points to some other string literals, thus printing (part of) them.
It is just pointer arithmetic. For instance,
cout << "num" + 1 << endl;
would print a string staring from ((address of)"num" + 1), i.e. "um".
If the value we add exceeds the length of the string, then we have undefined behavior.
Keep in mind that although iostreams overload << (and >>) to do I/O, these were originally defined as bit-shift operators. When the compiler's parsing the expression, it's basically seeing "operand, operator, operand", then checking whether the operands are of types to which that operator can be applied.
In this case, we have a string literal and (apparently) some sort of integer, and the compiler knows how to do math on those (after converting the string literal to a pointer).
From the compiler's viewpoint, however, this isn't a whole lot different from something like:
int a, b=1, c=2, d = 3;
a = b << c + d;
The difference is that with operands of type int, the meaning is fairly obvious: it's doing addition and bit-shifting. With iostreams, the meaning attached to << and >> change, but the syntax allowed for them in an expression is unchanged.
From the compiler's "viewpoint" the only question is whether the operands to + are of types for which + is allowed--in this case, you have pointer to char + integer, so that's allowed. The result is a pointer to char, and it has an overload of << that takes a left-hand operand of type ostream and a right-hand operator of type pointer to char, so the expression as a whole is fine (as far as it cares).
"num" type is char const [4]. If numSamples is integer, "num" + numSamples type is const char *. So you call operator << cor std::cout, that overloaded for const char * and prints string that starts from address addres("num") + numSamples in pointer arithmetic.
Try this:
cout << "num" + std::to_string(numSamples) << endl;
cout << "max" + std::to_string(maxSampleValue) << endl;
std::to_string() function you can find in <string>
if you look at operator_precedence, you will see that + gets evaluated before <<, which leaves this expression to be evaluated before being passed to the operator <<:
"num" + numSamples
Now "num" is going to be a static const char * and I'm assuming numSamples is an integral type. Since the left-hand side of the + is a pointer type and you are adding to it, that's pointer arithmetic. The cout now gets a pointer to a location in memory that is numSamples or maxSamplueValue more than the location of "num" or "max". Most likely all of your static strings were lined up in in the same region of memory which is why you saw them rather than random gibberish.

How to convert char* to unsigned short in C++

I have a char* name which is a string representation of the short I want, such as "15" and need to output this as unsigned short unitId to a binary file. This cast must also be cross-platform compatible.
Is this the correct cast: unitId = unsigned short(temp);
Please note that I am at an beginner level in understanding binary.
I assume that your char* name contains a string representation of the short that you want, i.e. "15".
Do not cast a char* directly to a non-pointer type. Casts in C don't actually change the data at all (with a few exceptions)--they just inform the compiler that you want to treat one type into another type. If you cast a char* to an unsigned short, you'll be taking the value of the pointer (which has nothing to do with the contents), chopping off everything that doesn't fit into a short, and then throwing away the rest. This is absolutely not what you want.
Instead use the std::strtoul function, which parses a string and gives you back the equivalent number:
unsigned short number = (unsigned short) strtoul(name, NULL, 0);
(You still need to use a cast, because strtoul returns an unsigned long. This cast is between two different integer types, however, and so is valid. The worst that can happen is that the number inside name is too big to fit into a short--a situation that you can check for elsewhere.)
#include <boost/lexical_cast.hpp>
unitId = boost::lexical_cast<unsigned short>(temp);
To convert a string to binary in C++ you can use stringstream.
#include <sstream>
. . .
int somefunction()
{
unsigned short num;
char *name = "123";
std::stringstream ss(name);
ss >> num;
if (ss.fail() == false)
{
// You can write out the binary value of num. Since you mention
// cross platform in your question, be sure to enforce a byte order.
}
}
that cast will give you (a truncated) integer version of the pointer, assuming temp is also a char*. This is almost certainly not what you want (and the syntax is wrong too).
Take a look at the function atoi, it may be what you need, e.g. unitId = (unsigned short)(atoi(temp));
Note that this assumes that (a) temp is pointing to a string of digits and (b) the digits represent a number that can fit into an unsigned short
Is the pointer name the id, or the string of chars pointed to by name? That is if name contains "1234", do you need to output 1234 to the file? I will assume this is the case, since the other case, which you would do with unitId = unsigned short(name), is certainly wrong.
What you want then is the strtoul() function.
char * endp
unitId = (unsigned short)strtoul(name, &endp, 0);
if (endp == name) {
/* The conversion failed. The string pointed to by name does not look like a number. */
}
Be careful about writing binary values to a file; the result of doing the obvious thing may work now but will likely not be portable.
If you have a string (char* in C) representation of a number you must use the appropriate function to convert that string to the numeric value it represents.
There are several functions for doing this. They are documented here:
http://www.cplusplus.com/reference/clibrary/cstdlib