What would be a declaration likechar *song;
What does the * does? Is it an array, a pointer or something else?
The * (Asterisk) indicates the variable is a pointer. As for a small example:
int x = 0;
int *y = &x; //y is pointing to x
const char* myText = "Text";
You might however be interested in learning a bit more about what pointers are.
H2CO3 is right, you should read up on c, and pointers.
char *song = "smb:d=4,o=5,b=......."
Is the does the same thing as the code below
char song[] = "smb:d=4,o=5,b=......."
In both cases song is a pointer to an array of strings. C++ has a string object, but plain C used c_strings. A c_string is simply a char array. You have what looks like a c_string.
*song //the same as "song[0]" will equal 's'
*(song+1) //the same as "song[1]" will equal 'm'
*(song+2) //the same as "song[2]" will equal 'b'
and so on
Related
I have a constant pointer cp that points to A and a non constant pointer p that points to B. I wold say that I can assign cp to p, i.e. p=cp because in this way both cp and p point to A and I cannot do the opposite: cp=p, because in this way I am saying that cp should point to B but cp is a constant pointer so I cannot change what it is pointing to.
I tried with this simple code but the result is the opposite, can someone explain me what is the correct version please?
std::vector<int> v;
v.push_back(0);
auto cp = v.cbegin(); // .cbegin() is constant
auto p = v.begin(); // .begin() is non constant
now if I write cp=p the compiler doesn't mark as error, but if I write p=cp the compiler marks the error.
cbegin is a pointer to something that is constant. You can change that pointer to point to something of the same constant type.
You're confusing this with a pointer, which is constant, to something that is not.
This is hard to see here, but the difference is between
const int* cp; // pointer to a constant value, but can point to something else
int* const pc; // pointer is constant, value can change
const int* const cpc; // pointer cannot be changed, value it points to cannot be changed
You can never make a "pointer that points to something that's not const" point at something that is const – because that means that you could change what is const, by derefencing the pointer!
const int value = 5; // can never change value
const int value2 = 10; // can never change value
const int* cp = &value; // our pointer to const int points at a const int
*cp = 6; // error: the value of something const can't be changed
cp = &value2; // fine, because we're pointing at a const int
int* p const = &value; // error: trying to point a pointer to non-const to a const, which would allow us to:
*p = 7; // which should be illegal.
int main()
{
int arr[]={2,3,5,6,8};
int *ptr;
ptr=&arr[3];
cout<<ptr-arr;
}
Q.why the answer is 3 after compiling the code i.e. as it should be 3*sizeof(int) which in this case should be 3*4=12?
When you subtract pointers you get the distance between them, not the allocated size. The same goes for iterators in STL.
https://en.cppreference.com/w/cpp/language/operator_arithmetic#Additive_operators
The reason is that it is much easier to write correct code.
When the pointer difference between consecutive elements of an array is 1, then you can use ++p to walk through the array (assuming p is a pointer to an element). For example:
int a[10];
for (auto p = a, e = a + 10; p != e; ++p)
*p = 42;
Notice how the code does not have to deal with the size of the elements. If the array type changes from int to double, the code does not have to change and is still correct.
#include<stdio.h>
int main(){
int a, b, c;
char *p = 0;
int *q = 0;
double *r = 0;
cout<<(int)(p + 1); // printing 1 char size
cout<<(int)(q + 1); // printing 4
cout<<(int)(r + 1); // printing 8
int y = 9;
int *u = &y;
cout<<(int)(u+1); //printing 7208688
cout<<*(p+1); //not able to dereferance
}
How is type-casting working in both the above case?
Why pointers p, q, r are unable to dereference?
Dereferencing any of p, q, r, p + 1, q + 1, r + 1 or u + 1 has undefined behaviour, because none of those pointers point to objects of the correct type.
You can add to a pointer, to get a different pointer value. This is only defined for results that stay within the same array, plus the "one-past-the-end" pointer value (treating a pointer to a single object as an array of length one). You can also convert a pointer to an integer type, to get an implementation defined value. Doing those things does not involve dereferencing the pointer.
Adding to a null pointer is also undefined behaviour, because the null pointer does not point to an object, there is nothing to be "one-past-the-end" of.
I am trying to understand how to use Cuda in Java. I am using jCuda.
Everything was fine until I came across an example containing the code:
// Set up the kernel parameters: A pointer to an array
// of pointers which point to the actual values.
Pointer kernelParameters = Pointer.to(
Pointer.to(new int[]{numElements}),
Pointer.to(deviceInputA),
Pointer.to(deviceInputB),
Pointer.to(deviceOutput)
);
The kernel function prototype is:
__global__ void add(int n, float *a, float *b, float *sum)
The question is:
In terms of c, does it not seem that we are passing something like?
(***n, ***a, ***b, ***sum)
So basically, do we always have to have:
Pointer kernelParameters = Pointer.to( double pointer, double pointer, ...)???
Thank you
The cuLaunchKernel function of JCuda corresponds to the cuLaunchKernel function of CUDA. The signature of this function in CUDA is
CUresult cuLaunchKernel(
CUfunction f,
unsigned int gridDimX,
unsigned int gridDimY,
unsigned int gridDimZ,
unsigned int blockDimX,
unsigned int blockDimY,
unsigned int blockDimZ,
unsigned int sharedMemBytes,
CUstream hStream,
void** kernelParams,
void** extra)
where the kernelParams is the only parameter that is relevant for this question. The documentation says
Kernel parameters can be specified via kernelParams. If f has N parameters, then kernelParams needs to be an array of N pointers. Each of kernelParams[0] through kernelParams[N-1] must point to a region of memory from which the actual kernel parameter will be copied.
The key point here is the last sentence: The elements of the kernelParams array are not the actual kernel parameters. They only point to the actual kernel parameters.
And indeed, this has the odd effect that for a kernel that receives a single float *pointer, you could basically set up the kernel parameters as follows:
float *pointer= allocateSomeDeviceMemory();
float** pointerToPointer = &pointer;
float*** pointerToPointerToPointer = &pointerToPointer;
void **kernelParams = pointerToPointerToPointer;
(This is just to make clear that this is indeed a pointer to a pointer to a pointer - in reality, wou wouldn't write it like that)
Now, the "structure" of the kernel parameters is basically the same for JCuda and for CUDA. Of course you can not take "the address of a pointer" in Java, but the number of indirections is the same. Imagine you have a kernel like this:
__global__ void example(int value, float *pointer)
In the CUDA C API, you can then define the kernel parameters as follows:
int value = 123;
float *pointer= allocateSomeDeviceMemory();
int* pointerToValue = &value;
float** pointerToPointer = &pointer;
void **kernelParams = {
pointerToValue,
pointerToPointer
};
The setup is done analogously in the JCuda Java API:
int value = 123;
Pointer pointer= allocateSomeDeviceMemory();
Pointer pointerToValue = Pointer.to(new int[]{value});
float** pointerToPointer = Pointer.to(pointer);
Pointer kernelParameters = Pointer.to(
pointerToValue,
pointerToPointer
);
The main difference that is relevant here is that you can write this a bit more concisely in C, using the address operator &:
void **kernelParams = {
&value, // This can be imagined as a pointer to an int
&pointer // This can be imagined as a pointer to a pointer
};
But this is basically the same as in the example that you provided:
Pointer kernelParameters = Pointer.to(
Pointer.to(new int[]{value}), // A pointer to an int
Pointer.to(pointer) // A pointer to a pointer
);
Again, the key point is that with something like
void **kernelParams = {
&value,
};
or
Pointer kernelParameters = Pointer.to(
Pointer.to(new int[]{value}),
);
you are not passing the value to the kernel directly. Instead, you are telling CUDA: "Here is an array of pointers. The first pointer points to an int value. Copy the value from this memory location, and use it as the actual value for the kernel call".
I'm trying to understand how String#capitalize! works internally. I can create a hash. Given string foo = "the", foo[0] is "t", look up the lower_case "t", and match it with upper case "T" value. In fact, Ruby source shows:
static VALUE
rb_str_capitalize_bang(VALUE str)
{
rb_encoding *enc;
char *s, *send;
int modify = 0;
unsigned int c;
int n;
str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
rb_str_check_dummy_enc(enc);
if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
s = RSTRING_PTR(str); send = RSTRING_END(str);
c = rb_enc_codepoint_len(s, send, &n, enc);
if (rb_enc_islower(c, enc)) {
rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
modify = 1;
}
s += n;
while (s < send) {
c = rb_enc_codepoint_len(s, send, &n, enc);
if (rb_enc_isupper(c, enc)) {
rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
modify = 1;
}
s += n;
}
if (modify) return str;
return Qnil;
}
The relevant function is toupper. How does it know toupper("t") equals "T"?
You're wondering how it knows what the uppercase version of the character is? Like most real-world implementations of this kind of function, it uses a lookup table.
toupper is an ansi C function. This means that the exact implementation actually depends on the provider of your library, which most of the times is your compiler.
Chances are that it follows the ASCII table, because there is no lookup as faster as a sum of integers - one of the steps in the lookup should involve a sum, to calculate the new address.
So, on gcc, we have this implementation
char
ctype<char>::do_toupper(char __c) const
{
int __x = __c;
return (this->is(ctype_base::lower, __c) ? (__x - 'a' + 'A') : __x);
}
This basically checks if it lower. If it is, returns the lower. Otherwise, it does subtracts 97 and then sum 65, which is the same thing than subtract 32. Remember that characters and numbers are the same for a computer, just binary data. And then, note how characters are used instead of numbers for a better readability (well, at least for C folks).
Without looking at any source code, I would guess that one way would be to convert a character to its' respective ASCII value, subtract 32 from it and convert the ASCII value back to a char.