为什么不能用另一个指向const char的指针初始化一个指针?

时间:2018-11-19 15:57:13

标签: c++ pointers const

这是我们在C ++类简介中得到的另一个“重塑方向”问题:

  

编写一个函数,该函数返回第一次出现的位置   字符串中的字符序列,即strstr的变体   功能。

我开始编写如下函数:

int strstr2(const char *text, const char *pattern) {
    int pos = 0;
    char *temp;
    temp = text;
}

我以为我会记住该函数的字符串的第一个字符的地址以供将来使用,但是编译器说:

  

不能将类型为“ const char *”的值分配给类型为“ char *”的实体。

我知道一旦初始化常量就无法更改常量,但是为什么我不能将指向常量char的指针分配给另一个非常量指针呢?

我阅读了一些有关指针和常量的问题,似乎在this帖子中被接受的答案的底部可能回答了我的问题,但我不确定百分百,因为讨论仍在进行中对我来说太高级了。

我的第二个问题是,解决方法是什么?如何定义一个指向字符串开头的指针?

谢谢。

3 个答案:

答案 0 :(得分:8)

这与const-correctness有关。 const char *text表示text是指向常量char的指针。这意味着如果您尝试做类似的事情

*text = 'a'

由于您尝试修改const对象,因此编译器将发出错误。如果可以的话

char *temp;
temp = text;

那你就可以做

*temp = 'a'

,即使您刚刚修改了const对象,也不会出错。这就是为什么C ++要求您实际上想抛弃const的情况下使用const_cast的原因(有一些用例,但到目前为止并不是您通常想要做的)。


危险,下面有龙。如果决定使用const_cast

,请非常小心

让我们说您必须处理一个仅需char*的旧API调用,但它保证不会修改,那么您可以使用类似

的方法
int wrap_api(const char *text)
{
    return api_call(const_cast<char*>(text));
}

,这将是“可以的”,因为api_call保证不会修改字符串。另一方面,如果api_call可以修改,那么只有在text指向的对象实际上不是像const这样的情况下,这才是合法的

char foo[] = "test"
wrap_api(foo);
如果foo被修改,但

将是合法的,但

const char foo* = "test"
wrap_api(foo);

如果foo被修改并且是未定义的行为,将是不合法的。

答案 1 :(得分:2)

如果允许分配,您将可以合法地写:

Option Explicit

Sub CopyMyStuff2()
    Dim wsSrc As Worksheet 'define source
    Set wsSrc = ThisWorkbook.Worksheets("SourceSheet")

    Dim wsDest As Worksheet 'define destination
    Set wsDest = ThisWorkbook.Worksheets("Sheet3")

    Dim FindList As Variant 'defind search words
    FindList = Array("Tank Engine", "Weatherman")

    Dim i As Long

    Dim FindItm As Variant
    For Each FindItm In FindList
        Dim CopyRange As Range
        Set CopyRange = FindMyRange(wsSrc.Range("A:L"), FindItm, "INFORMATION: " & FindItm)

        If Not CopyRange Is Nothing Then
            CopyRange.Copy wsDest.Range("A1").Offset(ColumnOffset:=i) 'note that if the first column uses merged cells the ColumnOffset:=i otherwise it is ColumnOffset:=i*12
            i = i + 1
        End If

    Next FindItm
End Sub

Function FindMyRange(SearchInRange As Range, ByVal StartString As String, ByVal EndString As String) As Range
   'find start
    Dim FoundStart As Range
    Set FoundStart = SearchInRange.Find(What:=StartString, LookAt:=xlWhole)

    If FoundStart Is Nothing Then GoTo ERR_NOTHING_FOUND

    'find end
    Dim FoundEnd As Range
    Set FoundEnd = SearchInRange.Find(What:=EndString, LookAt:=xlWhole, After:=FoundStart)

    If FoundEnd Is Nothing Then GoTo ERR_NOTHING_FOUND

    Set FindMyRange = SearchInRange.Parent.Range(FoundStart, FoundEnd).Resize(ColumnSize:=12)

    Exit Function

ERR_NOTHING_FOUND:
    FindMyRange = Nothing
End Function

但是在这种情况下,这会很糟糕,因为您将要写入一个常量。

标准可以表示*temp = 'x'; // write to char* is legal in general 分配是合法的,而temp = text是未定义的行为,但这没有任何意义,因为{{ 1}}和*text = 'x'是是否可以写入它。

因此,C ++禁止为T*类型分配const T*类型的值是为了避免以后做不好的事情,而是强迫您在其中使用T*,这是合乎逻辑的这种情况。

答案 2 :(得分:1)

这是const-correctness类型安全性的一部分。由于text是指向const char的指针,因此您无法修改它指向的字符。这是一件好事,也是一项安全措施。

但是,如果允许向非常量字符分配指针,则整个安全性将失效!因为比起您您可以通过上述指针修改字符并绕过安全性!

因此,不允许进行此分配。要修复它,请将您的temp也标记为const char指针:const char* temp